在WPF DataTemplate中运行时指定绑定路径 [英] Assign binding path at runtime in WPF DataTemplate

查看:234
本文介绍了在WPF DataTemplate中运行时指定绑定路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写在C#中的WPF程序中,我对这些列将在运行时填充一个ListView。我想用一个自定义的DataTemplate在ListView中GridViewColumn对象。

I am writing a WPF program in C# in which I have a ListView for which the columns will be populated at runtime. I would like to use a custom DataTemplate for the GridViewColumn objects in the ListView.

在我所见过的例子,列数是固定的提前,一个自定义的DataTemplate中使用类似下面的XAML往往创建。

In the examples I have seen where the number of columns is fixed in advance, a custom DataTemplate is often created using something like the XAML below.

<DataTemplate x:Key="someKey">
    <TextBlock Text="{Binding Path=FirstName}" />
</DataTemplate>

这DataTemplate中也稍后C-后面通过调用FindResource(someKey)分配给GridViewColumn.CellTemplate在$ C $。然而,仅凭这对我没有用的,因为在这个例子中,Path元素被固定为姓。真的,我需要的东西,我可以设置code中的路径。

This DataTemplate could also later be assigned to GridViewColumn.CellTemplate in the code-behind by calling FindResource("someKey"). However, this alone is of no use to me, because in this example the Path element is fixed to FirstName. Really I need something where I can set the Path in code.

这是我的IM pression,如果使用XamlReader沿着这些路线的东西是可能的,但我不知道如何在实践中我会做到这一点。任何解决方案都大大AP preciated。

It is my impression that something along these lines may be possible if XamlReader is used, but I'm not sure how in practice I would do this. Any solutions are greatly appreciated.

推荐答案

这是很容易建立你所需要的使用两个的DataTemplates协同工作:外的DataTemplate只是设置的DataContext的内DataTemplate中,如下所示:

It is easy to build what you need using two DataTemplates working in concert: The outer DataTemplate simply sets the DataContext for the inner DataTemplate, as follows:

<DataTemplate x:Key="DisplayTemplate">
  <Border ...>
    <TextBlock Text="{Binding}" ... />
  </Border>
</DataTemplate>

<DataTemplate x:Key="CellTemplate">
  <ContentPresenter Content="{Binding FirstName}"
                    ContentTemplate="{StaticResource DisplayTemplate}" />
</DataTemplate>

唯一棘手的事情是使它方便地设置此一GridViewColumn。我会附加属性做到这一点,让你写:

The only tricky thing is making it convenient to set this on a GridViewColumn. I would accomplish this with attached properties, allowing you to write:

<GridViewColumn
  my:GVCHelper.DisplayPath="FirstName"
  my:GVCHelper.Template="{StaticResource DisplayTemplate}" />

或等价于code:

var col = new GridViewColumn();
GVCHelper.SetDisplayPath(col, "FirstName");
GVCHelper.SetTemplate(col, (DataTemplate)FindResource("DisplayTemplate"));

无论这些会导致名为DisplayTemplate中的DataTemplate中使用的列中显示名字。

Either of these would cause the DataTemplate named "DisplayTemplate" to be used to display the FirstName in the column.

helper类将实现为:

The helper class would be implemented as:

public class GVCHelper : DependencyObject
{
  public static string GetDisplayPath(DependencyObject obj) { return (string)obj.GetValue(DisplayPathProperty); }
  public static void SetDisplayPath(DependencyObject obj, string value) { obj.SetValue(DisplayPathProperty, value); }
  public static readonly DependencyProperty DisplayPathProperty = DependencyProperty.RegisterAttached("DisplayPath", typeof(string), typeof(GVCHelper), new PropertyMetadata
  {
    PropertyChangedCallback = (obj, e) => Update(obj)
  });

  public static DataTemplate GetTemplate(DependencyObject obj) { return (DataTemplate)obj.GetValue(TemplateProperty); }
  public static void SetTemplate(DependencyObject obj, DataTemplate value) { obj.SetValue(TemplateProperty, value); }
  public static readonly DependencyProperty TemplateProperty = DependencyProperty.RegisterAttached("Template", typeof(DataTemplate), typeof(GVCHelper), new PropertyMetadata
  {
    PropertyChangedCallback = (obj, e) => Update(obj)
  });

  private static void Update(DependencyObject obj)
  {
    var path = GetDisplayPath(obj);
    var template = GetTemplate(obj);
    if(path!=null && template!=null)
    {
      var factory = new FrameworkElementFactory(typeof(ContentPresenter));
      factory.SetBinding(ContentPresenter.ContentProperty, new Binding(path));
      factory.SetValue(ContentPresenter.ContentTemplateProperty, template);
      obj.SetValue(GridViewColumn.CellTemplateProperty,
        new DataTemplate { VisualTree = factory };
    }
  }
}

它是如何工作:每当这两种属性集,新的DataTemplate构造和GridViewColumn.CellTemplate属性更新

How it works: Whenever the properties are both set, a new DataTemplate is constructed and the GridViewColumn.CellTemplate property is updated.

这篇关于在WPF DataTemplate中运行时指定绑定路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆