【问题标题】:WPF - DataTemplate questionWPF - 数据模板问题
【发布时间】:2011-04-20 19:58:13
【问题描述】:

我用一个按钮对一个网格标题进行数据模板化。单击按钮时,我想将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>

【问题讨论】:

  • 您使用的是哪个版本的 .NET? CommandParameter 在 4.0 之前的版本中不可绑定。
  • 我使用的是 4.0.我在过去的 4 个小时里都在尝试这个,但想不通。虽然看起来很简单。我需要的只是从数据模板绑定到父级的属性。这似乎是一个严重的错误,或者我错过了什么......

标签: wpf wpf-controls binding wpfdatagrid


【解决方案1】:

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

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

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

【讨论】:

  • 问题是网格的标题会受到本地化并且会改变。所以不能使用标题文本。
  • @Mani - 我同意,这个新答案更好一些,因为它有效,但我仍然觉得它可以改进。让我知道这是否会让您前进,如果您做出改进,请发布新答案。
  • @zamboni-我现在完全一样,它解决了问题。感谢您为实现这一目标所做的努力。将与 MS 人员跟进以了解其确切原因。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-01
  • 2021-12-25
相关资源
最近更新 更多