WPF DataGrid CellTemplateSelector 项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31340606/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF DataGrid CellTemplateSelector Item
提问by user1514042
I have a grid bound to a collection of VMs. When using DataTemplateSelectorfor my DataGridTemplateColumnI'm getting the whole VM as a data item, how do I narrow it down to a specific property value (otherwise I have to create 'DataTemplateSelector' for each VM or use interfaces, with both are too cumbersome) ?
我有一个绑定到一组 VM 的网格。当DataTemplateSelector我DataGridTemplateColumn将整个 VM 作为数据项使用时,如何将其缩小到特定的属性值(否则我必须为每个 VM 创建“DataTemplateSelector”或使用接口,两者都太麻烦)?
Saw Bind a property to DataTemplateSelector, but it looks like a nasty workaround.
看到Bind a property to DataTemplateSelector,但它看起来像一个讨厌的解决方法。
回答by Il Vic
You can use Expressions Treesin a DataTemplateSelector's derived class, that I called PropertyTemplateSelector. Here its code:
您可以在 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);
}
You can extend this class with your own logic, just by implementing the SelectTemplateImplmethod. As you can see the PropertyTemplateSelectornarrows the item object down to a specific property value (which is passed to the SelectTemplateImplmethod). For example I created a NameTemplateSelectorin this way:
您可以使用自己的逻辑扩展此类,只需实现该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");
}
}
The you can easly use these template selectors in your XAML
您可以在 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>
I hope it can help you.
我希望它能帮助你。

