2010-06-09 5 views
1

J'écris un programme WPF en C# dans lequel j'ai un ListView pour lequel les colonnes seront remplies lors de l'exécution. Je voudrais utiliser un DataTemplate personnalisé pour les objets GridViewColumn dans ListView.Affectation d'un chemin de liaison à l'exécution dans WPF DataTemplate

Dans les exemples, j'ai vu où le nombre de colonnes est fixé à l'avance, un DataTemplate personnalisé est souvent créé en utilisant quelque chose comme le XAML ci-dessous.

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

Ce DataTemplate pourrait aussi être affecté à plus tard GridViewColumn.CellTemplate dans le code-behind en appelant FindResource ("someKey"). Cependant, cela seul ne me sert à rien, car dans cet exemple l'élément Path est fixé à FirstName. Vraiment j'ai besoin de quelque chose où je peux définir le chemin dans le code.

J'ai l'impression que quelque chose de ce genre peut être possible si XamlReader est utilisé, mais je ne suis pas sûr de la façon dont je le ferais en pratique. Toutes les solutions sont grandement appréciées.

Répondre

2

Il est facile de construire ce dont vous avez besoin en utilisant deux DataTemplates qui fonctionnent de concert: Le DataTemplate externe définit simplement le DataContext pour l'intérieur DataTemplate, comme suit:

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

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

La seule chose délicate rend commode de mettre cela sur un GridViewColumn. Je cette fin avec des propriétés attachées, vous permettant d'écrire:

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

ou de manière équivalente dans le code:

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

Chacune de ces causerait le DataTemplate nommé « DisplayTemplate » à utiliser pour afficher la FirstName dans la colonne.

La classe d'aide serait mis en œuvre comme:

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 }; 
    } 
    } 
} 

Comment ça marche: Chaque fois que les propriétés sont tous deux, un nouveau DataTemplate est construit et la propriété GridViewColumn.CellTemplate est mis à jour.

0

Peut-être que GridViewColumn.CellTemplateSelector pourrait vous aider? Ou vous pouvez créer un contrôle utilisateur, le lier à quelque chose de suffisamment grand (c'est la même chose pour chaque colonne). Ensuite, laissez ce contrôle comprendre ce qu'il doit afficher exactement en fonction de ce qu'il a dans ...

Questions connexes