在WPF DataTemplate中在运行时分配绑定路径

时间:2010-06-09 19:06:59

标签: wpf listview

我正在用C#编写一个WPF程序,其中我有一个ListView,其列将在运行时填充。我想在ListView中为GridViewColumn对象使用自定义DataTemplate。

在我已经看到预先修复了列数的示例中,通常使用类似下面的XAML创建自定义DataTemplate。

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

稍后可以通过调用FindResource(“someKey”)将此DataTemplate分配给代码隐藏中的GridViewColumn.CellTemplate。但是,这对我来说没有用,因为在这个例子中,Path元素被固定为FirstName。我真的需要能在代码中设置路径的东西。

我的印象是,如果使用XamlReader,可能会出现这些问题,但我不确定实际上我会怎么做。非常感谢任何解决方案。

2 个答案:

答案 0 :(得分:2)

使用两个协同工作的DataTemplates很容易构建您需要的东西:外部DataTemplate只是为内部DataTemplate设置DataContext,如下所示:

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

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

唯一棘手的事情就是在GridViewColumn上设置它很方便。我将使用附加属性完成此操作,允许您编写:

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

或等同于代码:

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

其中任何一个都会导致名为“DisplayTemplate”的DataTemplate用于显示列中的FirstName。

辅助类将实现为:

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属性。

答案 1 :(得分:0)

也许GridViewColumn.CellTemplateSelector可以帮到你?或者你可以创建一个用户控件,将它绑定到足够大的东西(每列相同)。然后让这个控件根据DataContext ...

中的内容确定应该显示的内容