2

This is my first post on stackoverlow which I consider the best online help site for C# and WPF.

I have researched about six+ hours over the past three days trying to figure out how to attach a button handler event to a button I have defined in a style. My situation seems to be different than all the other examples I have looked at on the web. So here goes and I certainly appreciate your input.

A snippet from MainWindow.xaml where I define within a Grid the following

 <ScrollViewer Grid.Column="2" Grid.ColumnSpan="2" 
      HorizontalScrollBarVisibility="Visible" 
      VerticalScrollBarVisibility="Hidden"
      Background="AliceBlue">
    <ItemsControl ItemsSource="{Binding LaserDataItems}">
       <ItemsControl.ItemsPanel>
           <ItemsPanelTemplate>
               <StackPanel Orientation="Horizontal" Background="AliceBlue" />
       </ItemsPanelTemplate>
      </ItemsControl.ItemsPanel>
    </ItemsControl> 
  </ScrollViewer>

This binding on LaserDataItems will contain a list of the UserControls to display.These are created dynamically as needed. But I actually attempt to do all my work in the code behind of the control (below)

Before I show you the UserControl, here is the Style that I am going to use with the UserControl. My first goal is to create click event on the button after it is loaded

<Style x:Key="HeaderStyle" TargetType="{x:Type DataGridColumnHeader}">            
  <Setter Property="Template">
     <Setter.Value>
        <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
           <Button   x:Name="MyButton"    Height="20"/>
        </ControlTemplate>
     </Setter.Value>
  </Setter>
</Style>

Here is the userControl

<UserControl x:Class="EClient.Controls.GetAllLaserData"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <DataGrid Name="laserDataGrid" 
              ColumnHeaderStyle="{StaticResource HeaderStyle}"
              AutoGenerateColumns="False" 
              ItemsSource="{Binding }" 
              IsReadOnly="True" 
              RowHeaderWidth="0" 
              Height="567" 
              VerticalAlignment="Top" 
              RowHeight="17">
        <DataGrid.Columns>
            <DataGridTextColumn 
             Width="53" 
             Header="{Binding HeaderName}" 
             Binding="{Binding Name}"></DataGridTextColumn>
        </DataGrid.Columns>
        <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Setter Property="IsEnabled" Value="False"/>
            </Style>
        </DataGrid.RowStyle>
    </DataGrid>
</UserControl>

Within the DataGrid of this UserControl is a ColumnHeaderStyle which is assigned the template: HeaderStyle. This style has the button which I need to attach a click handler to whenever it is instantiated. How do I do this. I have tried to access it by overriding the OnApplyTemplate method but everything I try returns null. Is it possible that the button has not yet been instantiated when this method runs? There must be a way to get to this button.

When I run this and successfully create a list of these UserControls (which are datagrids) a button can be seen in the first cell (which is the header of each grid).

I also tried using a generic routine that traverses the visual tree but to no avail. Actually is this something that I should pursue, I'm really at a loss for ideas to try.


The following piece was added on 10/26/2013

Although i have found another solution to this problem, I am still interested in resolving it. I really thought it was a pretty good question.

Anyway, I thought I would place a picture of what I was trying to do. Perhaps that would place a better perspective on the problem in hand.

Datagrid with Button Above Grid

New Alexandria
  • 6,951
  • 4
  • 57
  • 77
Rick
  • 65
  • 1
  • 9
  • These links may help: http://stackoverflow.com/questions/4030764/how-to-get-datagridcolumnheader-from-datagridcolumn http://stackoverflow.com/questions/1658397/wpf-datagrid-header-text-binding (May not). – Chris Oct 27 '13 at 11:47
  • Chris, These links really look promising. Thank You. When I get back into town I will give them a try and get let you know. Thanks, again - Rick – Rick Oct 28 '13 at 17:15
  • Hopefully something useful in there, I had a crack at something myself, it didn't work and stumbled across those when trying to understand why. – Chris Oct 28 '13 at 22:23
  • Chris, These links were really good but they did not work for me. Unfortunately I am not a full-time WPF developer so I could only spend an hour or so last night to determine if I could access the button. I may go back and revisit / study later on. Again, thanks - Rick – Rick Oct 30 '13 at 19:07

1 Answers1

0

Not a direct answer - but here is how I would approach the problem. I don't use datagrids - favouring itemscontrols instead, so I'll have to use an ItemsControl for the example.

When handling buttons in lists, I usually split the control containing the button out into its own user control (applying the style as required). I would then have an event handler in the background e.g. XAML

<UserControl x:Class="BindableTest.UserControls.CatItem"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="400">
  <StackPanel VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0 0 10 0">
    <Label Content="{Binding Path=Model.DisplayNumber}" HorizontalAlignment="Left" Height="25" Width="25" />
    <TextBox BorderBrush="Black" Text="{Binding Path=Model.SomeText, UpdateSourceTrigger=PropertyChanged}" Width="150" Height="25" />
    <StackPanel Orientation="Horizontal">
      <Button x:Name="btnDelete" Margin="5 0 0 0" Content="Delete" Click="btnDelete_Click_1"></Button>
    </StackPanel>
  </StackPanel>
</UserControl>

and code behind...

  /// <summary>
  /// Interaction logic for CatItem.xaml
  /// </summary>
  public partial class CatItem : UserControl
  {
    public CatItem()
    {
      InitializeComponent();     
    }

    private void btnDelete_Click_1(object sender, RoutedEventArgs e)
    {
      if (DeleteClick != null)
        DeleteClick(sender, e);
    }

    public event RoutedEventHandler DeleteClick;


  }

From the calling xaml, you can then use this event as shown below.

<ItemsControl x:Name="itmsList" ItemsSource="{Binding Path=ModelListVMs}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <StackPanel Orientation="Horizontal"></StackPanel>
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <uc:CatItem DeleteClick="ItemDeleteClick"></uc:CatItem> <!-- Using click here -->
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

In the background of the window you can then pick up the event for any button.

public void ItemDeleteClick(object sender, RoutedEventArgs e)
    {
      var ctx = (sender as Button);

      //can get datacontext and other properties easily from here  
    }

Sorry it's not a direct answer, but hopefully it will help you in the right direction.

JsAndDotNet
  • 16,260
  • 18
  • 100
  • 123
  • 1
    HockeyJ, Thanks so much for your feedback. Although it does not answer my question, it did give me the idea to redesign my control. I pulled the button out of the Control-template and instead put it (the button) into a Stack-panel (with the Button above the Data-grid). I'm still curious as to why I could not find the Button. When I recursively went through the Visual tree of the Data-grid using the laserGataGrid reference, what I believe I saw was The ancestry of the Data-grid definition and not my customized one. So still looking for an answer but I really appreciate your feedback. – Rick Oct 25 '13 at 17:30
  • @Rick: If you have more information to add, add it to the original question, not the answer. – Makoto Oct 27 '13 at 05:56
  • Thanks Makato. I will do so. – Rick Oct 28 '13 at 16:46