2010-06-09 6 views
1

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

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

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

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

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

ответ

2

Легко построить то, что вам нужно, используя два 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», который будет использоваться для отображения ПгвЬЫате в колонке.

Вспомогательный класс будет реализован как:

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

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

Смежные вопросы