WPF - 数据模板问题

发布于 2024-09-26 00:17:27 字数 877 浏览 1 评论 0原文

我将一个带有按钮的网格标题数据模板化。单击按钮时,我想发送 uid(这是网格列(父级)的属性)作为命令参数

我试过 : 1. 模板绑定 2. 相关来源 3. ElementName(不接受绑定) 但似乎没有任何作用。任何线索,如何绑定到数据模板中父级的属性?

<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>

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心凉 2024-10-03 00:17:27

编辑:这是一个新答案;我把旧的答案留在了底部。

如果设置 Path=.在 CommandParameter 中,您将 ContentPresenter 作为命令中的对象。此时我仍然无法引用列的 Uid 或名称。因此,我创建了继承自 DataGridTextColumn 的 DataGridTextColumnWithTag,并添加了一个名为 Tag 的 DependencyProperty。现在,在 OnDrilldownHeaderClicked 中,我可以确定在网格中单击的列。

这是 XAML 中的 DataTemplate:

<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>

这是 XAML 中 DataGrid 列的定义:

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

这是新的 DataGrid 列:

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));
}

这是用于查找单击的列的命令绑定:

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;
         }
      }
   }
}

注意:这是旧的回答。此代码获取列标题,但如果/当列名称更改时,该代码会很脆弱。

以下 DataTemplate 获取列的标题。
然后我使用标题来找出该列。
希望这能让您开始。
如果您可以扩展此解决方案,请发布您的答案。

<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>

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文