Назначить путь привязки во время выполнения в WPF DataTemplate - PullRequest
1 голос
/ 09 июня 2010

Я пишу программу WPF на C #, в которой у меня есть ListView, для которого столбцы будут заполняться во время выполнения. Я хотел бы использовать пользовательский шаблон DataTemplate для объектов GridViewColumn в ListView.

В примерах, которые я видел, где количество столбцов заранее фиксировано, пользовательский шаблон данных часто создается с использованием чего-то вроде XAML ниже.

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

Этот DataTemplate позже также может быть назначен для GridViewColumn.CellTemplate в выделенном коде путем вызова FindResource ("someKey"). Однако это само по себе бесполезно, потому что в этом примере элемент Path зафиксирован на FirstName. На самом деле мне нужно что-то, где я могу установить путь в коде.

У меня сложилось впечатление, что что-то в этом роде может быть возможным, если использовать XamlReader, но я не уверен, как на практике я бы это сделал. Любые решения приветствуются.

Ответы [ 2 ]

2 голосов
/ 11 июня 2010

Легко построить то, что вам нужно, используя два DataTemplates, работающие согласованно: внешний DataTemplate просто устанавливает DataContext для внутреннего DataTemplate следующим образом:

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

Любое из этих действий приведет к использованию DataTemplate с именем «DisplayTemplate»для отображения 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 обновлено.

0 голосов
/ 09 июня 2010

Может быть GridViewColumn.CellTemplateSelector вам поможет?Или вы можете создать пользовательский элемент управления, привязать его к чему-то достаточно большому (это одинаково для каждого столбца).Затем пусть этот элемент управления выяснит, что именно он должен отображать, основываясь на том, что он имеет в DataContext ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...