Everything Matters
Everything Matters

Reputation: 2740

WPF - DataTemplate question

I datatemplate a grid header with a button. When the button is clicked, I want to send the uid (which is a property of the grid column(parent)) as the command parameter.

I Tried : 1. Template Binding 2. Relative Source 3. ElementName (doesnt accpet Binding) But nothing seems to work. Any clue, how to bind to a parent's property in datatemplate?

<UserControl.Resources>
       <DataTemplate x:Key="ClickableHeaderTemplate">
            <Button x:Name="btn"  Content="{Binding}" Background="Transparent" 
                  Command="{Binding DrilldownHeaderClicked}" 
                  CommandParameter="{Binding ElementName=????, Path=Uid}" >
            </Button>
        </DataTemplate>
    </UserControl.Resources>

<DataGrid>
 <DataGridTextColumn x:Name="TotalOid" x:Uid="PhMg5Ph-Oid"  
  Binding="{Binding TotalOid, Mode=OneWay,TargetNullValue=-}"
 Header="Col1" 
 HeaderTemplate="{StaticResource ResourceKey=ClickableHeaderTemplate}">
</DataGridTextColumn>
</Datagrid>

Upvotes: 1

Views: 909

Answers (1)

Zamboni
Zamboni

Reputation: 8043

Edit: this a new answer; I left the old answer at the bottom.

If you set Path=. in the CommandParameter you get the ContentPresenter as the object in the Command. At this point I still could not reference the Uid or Name of the Column. Thus I created DataGridTextColumnWithTag that inherits from DataGridTextColumn and I added a DependencyProperty called Tag. Now in OnDrilldownHeaderClicked I can determine the column clicked on in the Grid.

Here is the DataTemplate in XAML:

<Window.Resources>
    <c:CommandReference x:Key="DrilldownHeaderClickedReference" Command="{Binding DrilldownHeaderClicked}" />
    <DataTemplate x:Key="ClickableHeaderTemplate">
        <Button Content="{Binding}" Background="Transparent"  
                Command="{StaticResource DrilldownHeaderClickedReference}"  
                CommandParameter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=.}" >
        </Button>
    </DataTemplate>
</Window.Resources>

Here is the definition of the DataGrid Column in XAML:

<Helpers:DataGridTextColumnWithTag 
    Header="Extra Name" 
    Tag="234"
    Width="SizeToCells"
    Binding="{Binding FinalName}" 
    FontSize="20" 
    HeaderTemplate="{StaticResource ResourceKey=ClickableHeaderTemplate}">
</Helpers:DataGridTextColumnWithTag>

Here is the new DataGrid column:

public class DataGridTextColumnWithTag : DataGridTextColumn
{
  public DataGridTextColumnWithTag() : base() { }

  public string Tag
  {
     get { return (string)this.GetValue(TagProperty); }
     set { this.SetValue(TagProperty, value); }
  }

  public static readonly DependencyProperty TagProperty = DependencyProperty.Register(
    "Tag", typeof(string), typeof(DataGridTextColumnWithTag), new PropertyMetadata(string.Empty));
}

Here is Command Binding used to find the column clicked on:

public ICommand DrilldownHeaderClicked { get; set; }
private void OnDrilldownHeaderClicked(object obj)
{
   ContentPresenter cp = obj as ContentPresenter;
   if (cp != null)
   {
      DataGridColumnHeader tp = cp.TemplatedParent as DataGridColumnHeader;
      if ( tp != null )
      {
         DataGridTextColumnWithTag column = tp.Column as DataGridTextColumnWithTag;
         if ( column != null )
         {
            string tag = column.Tag;
         }
      }
   }
}

Note: this is the old answer. This code gets the column header, but is brittle if/when the Column name changes.

The following DataTemplate gets me the Header of the column.
I then use the header to figure out the column.
Hopefully this gets you started.
If you can extend this solution please post your answer.

<UserControl.Resources>
    <c:CommandReference x:Key="DrilldownHeaderClickedReference" Command="{Binding DrilldownHeaderClicked}" />

    <DataTemplate x:Key="ClickableHeaderTemplate">
        <Button x:Name="btn"  Content="{Binding}" Background="Transparent"  
              Command="{StaticResource DrilldownHeaderClickedReference}"  
              CommandParameter="{Binding}" >
        </Button>
    </DataTemplate>
</UserControl.Resources>

Upvotes: 2

Related Questions