WPF DataGrid CellTemplateSelector Item

本文关键字:Item CellTemplateSelector DataGrid WPF | 更新日期: 2023-09-27 18:02:08

我有一个绑定到虚拟机集合的网格。当使用DataTemplateSelector为我的DataGridTemplateColumn我得到整个虚拟机作为一个数据项,我如何缩小到一个特定的属性值(否则我必须创建'DataTemplateSelector'为每个虚拟机或使用接口,两者都太麻烦)?

WPF DataGrid CellTemplateSelector Item

将属性绑定到DataTemplateSelector,但它看起来像一个讨厌的解决方案。

您可以在DataTemplateSelector的派生类中使用表达式树,我称之为PropertyTemplateSelector。下面是它的代码:

public abstract class PropertyTemplateSelector : DataTemplateSelector
{
    private Delegate getPropertyValue;
    private string propertyName;
    private Type itemType;
    public string PropertyName
    {
        get
        {
            return propertyName;
        }
        set
        {
            propertyName = value;
        }
    }
    public Type ItemType
    {
        get
        {
            return itemType;
        }
        set
        {
            itemType = value;
        }
    }
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (ItemType.IsInstanceOfType(item))
        {
            if (getPropertyValue == null)
            {
                System.Linq.Expressions.ParameterExpression instanceParameter =
                    System.Linq.Expressions.Expression.Parameter(item.GetType(), "p");
                System.Linq.Expressions.MemberExpression currentExpression =
                    System.Linq.Expressions.Expression.PropertyOrField(instanceParameter, PropertyName);
                System.Linq.Expressions.LambdaExpression lambdaExpression =
                    System.Linq.Expressions.Expression.Lambda(currentExpression, instanceParameter);
                getPropertyValue = lambdaExpression.Compile();
            }
            return SelectTemplateImpl(getPropertyValue.DynamicInvoke(item), container);
        }
        return base.SelectTemplate(item, container);
    }
    protected abstract DataTemplate SelectTemplateImpl(object propertyValue, DependencyObject container);
}

您可以用自己的逻辑扩展这个类,只需实现SelectTemplateImpl方法。正如您所看到的,PropertyTemplateSelector将item对象缩小到一个特定的属性值(传递给SelectTemplateImpl方法)。例如,我以这种方式创建了一个NameTemplateSelector:

public class NameTemplateSelector : PropertyTemplateSelector
{
    protected override DataTemplate SelectTemplateImpl(object propertyValue, DependencyObject container)
    {
        string name = (string)propertyValue;
        if (name != null && name.StartsWith("A", StringComparison.OrdinalIgnoreCase))
        {
            return (DataTemplate)App.Current.MainWindow.FindResource("VipName");
        }
        return (DataTemplate)App.Current.MainWindow.FindResource("NormalName");
    }
}

你可以很容易地在你的XAML

中使用这些模板选择器
<Window.Resources>
    <DataTemplate x:Key="NormalName">
        <TextBlock Text="{Binding Mode=OneWay, Path=Name}" Margin="3" />
    </DataTemplate>
    <DataTemplate x:Key="VipName">
        <TextBlock Text="{Binding Mode=OneWay, Path=Name}" Margin="3" Foreground="Red" FontWeight="Bold" />
    </DataTemplate>
    <DataTemplate x:Key="NormalSurname">
        <TextBlock Text="{Binding Mode=OneWay, Path=Surname}" Margin="3" />
    </DataTemplate>
    <DataTemplate x:Key="VipSurname">
        <TextBlock Text="{Binding Mode=OneWay, Path=Surname}" Margin="3" Foreground="Green" FontStyle="Italic" />
    </DataTemplate>
    <local:NameTemplateSelector x:Key="NameTemplateSelector" PropertyName="Name" ItemType="{x:Type local:Person}" />
    <local:SurnameTemplateSelector x:Key="SurnameTemplateSelector" PropertyName="Surname" ItemType="{x:Type local:Person}" />
</Window.Resources>
<Grid>
    <DataGrid ItemsSource="{Binding Path=People, Mode=OneWay}" AutoGenerateColumns="False"
                CanUserAddRows="False">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Name"
                                    CellTemplateSelector="{StaticResource NameTemplateSelector}" />
            <DataGridTemplateColumn Header="Surname"
                                    CellTemplateSelector="{StaticResource SurnameTemplateSelector}" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

我希望它能帮助你。