2010-06-09 29 views
1

我正在寫一個WPF程序在C#中,我有一個ListView的列將在運行時填充。我想爲ListView中的GridViewColumn對象使用自定義DataTemplate。WPF DataTemplate在運行時分配綁定路徑

在我已經看到列數已預先確定的例子中,通常使用類似下面的XAML創建自定義DataTemplate。

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

此DataTemplate中也後來通過調用FindResource(「someKey」)被分配給GridViewColumn.CellTemplate在代碼隱藏。然而,這對我來說沒有用處,因爲在這個例子中,Path元素被固定爲FirstName。真的,我需要一些可以在代碼中設置路徑的地方。

這是我的印象是,如果使用XamlReader的話,沿着這些線可能是可能的,但我不知道如何在實踐中我會這樣做。任何解決方案,不勝感激。

回答

2

使用兩個DataTemplates協同工作可以輕鬆構建您所需的內容:外部DataTemplate只需將DataContext設置爲inner 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")); 

無論這些會導致名爲「DisplayTemplate」的DataTemplate中被用於顯示姓在列中。

助手類將被實現爲:

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中的內容確定它應該顯示的內容...