行的 WPF DataGrid StyleSelector
WPF DataGrid StyleSelector for Rows
我正在尝试使用 ItemContainerStyleSelector 根据定义行的对象类型在数据网格中显示不同的行样式(ItemsSource 是 IGridItem
的集合,有 GridItem
和 GridSeparator
应该得到不同的样式)。我的问题是,我的 StyleSelector 的 SelectStyle
从未被调用过。现在我发现(here)问题可能是继承样式(MahApps Metro 库重新定义了所有标准控件的默认样式),它可能已经设置了 ItemContainerStyle。
所以现在我的问题是:有没有办法仍然使用我的 StyleSelector,以便我将继承的样式作为所选样式的基础?如果没有,我如何根据对象类型为某些行实现不同的样式?
编辑:
手动将 ItemContainerStyle 设置为 null
没有效果,我的 StyleSelector 的 SelectStyle
仍然没有被调用。
编辑 2:
因为我没有像 Grx70 那样得到 System.Windows.Data Error: 24 : Both 'ItemContainerStyle' and 'ItemContainerStyleSelector' are set; 'ItemContainerStyleSelector' will be ignored.
,所以我假设 ItemContainerStyle 不是问题,就像我最初想的那样。
jstreet 指出,它与 MahApps.Metro 有关,但...(请参阅他的评论)
我当前的实现:
<DataGrid ItemsSource="{Binding Items}" ItemContainerStyleSelector="{StaticResource StyleSelector}">
样式选择器:
public class GridRowStyleSelector : StyleSelector
{
private readonly ResourceDictionary _dictionary;
public GridRowStyleSelector()
{
_dictionary = new ResourceDictionary
{
Source = new Uri(@"pack://application:,,,/myApp;component/View/GridResources.xaml")
};
}
public override Style SelectStyle(object item, DependencyObject container)
{
string name = item?.GetType().Name;
if (name != null && _dictionary.Contains(name))
{
return (Style)_dictionary[name];
}
return null;
}
}
GridResources.xaml 测试值:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="GridItem" TargetType="DataGridRow">
<Setter Property="BorderThickness" Value="3"/>
</Style>
<Style x:Key="GridSeparator" TargetType="DataGridRow">
<Setter Property="BorderBrush" Value="Red"/>
</Style>
</ResourceDictionary>
您可以通过明确将其设置为 null
来覆盖默认值 ItemContainerStyle
:
<DataGrid ItemsSource="{Binding Items}"
ItemContainerStyle="{x:Null}"
ItemContainerStyleSelector="{StaticResource StyleSelector}">
GridRowStyleSelector 的构造函数class 是静态和私有的。
尝试从此 class 中删除 'static' 关键字,并使构造函数 public.
我想我找到了罪魁祸首。结果表明,在 DataGrid
中处理行样式的正确方法是通过 RowStyle
和 RowStyleSelector
属性,而不是 ItemContainerStyle
和 ItemContainerStyleSelector
。它们可以工作,但只有在您明确使用 RowStyle
或 RowStyleSelector
时才会起作用。这正是 MahApps Metro 所做的 - 它设置 RowStyle
值(我相信通过覆盖 DataGrid
默认样式)。然后我认为 ItemContainerStyle
是由 DataGrid
内部设置的(一些测试显示 ItemContainerStyle
已设置,尽管明确将其设置为 null
)。
总而言之,这应该可以解决您的问题:
<DataGrid ItemsSource="{Binding Items}"
RowStyle="{x:Null}"
RowStyleSelector="{StaticResource StyleSelector}">
(...)
</DataGrid>
此外,要修改 MahApps 行样式而不是完全丢弃它,您应该将您的样式基于 MahApps 行样式:
<Style x:Key="GridItem" TargetType="DataGridRow"
BasedOn="{StaticResource MetroDataGridRow}">
<Setter Property="BorderThickness" Value="3"/>
</Style>
<Style x:Key="GridSeparator" TargetType="DataGridRow"
BasedOn="{StaticResource MetroDataGridRow}">
<Setter Property="BorderBrush" Value="Red"/>
</Style>
我正在尝试使用 ItemContainerStyleSelector 根据定义行的对象类型在数据网格中显示不同的行样式(ItemsSource 是 IGridItem
的集合,有 GridItem
和 GridSeparator
应该得到不同的样式)。我的问题是,我的 StyleSelector 的 SelectStyle
从未被调用过。现在我发现(here)问题可能是继承样式(MahApps Metro 库重新定义了所有标准控件的默认样式),它可能已经设置了 ItemContainerStyle。
所以现在我的问题是:有没有办法仍然使用我的 StyleSelector,以便我将继承的样式作为所选样式的基础?如果没有,我如何根据对象类型为某些行实现不同的样式?
编辑:
手动将 ItemContainerStyle 设置为 null
没有效果,我的 StyleSelector 的 SelectStyle
仍然没有被调用。
编辑 2:
因为我没有像 Grx70 那样得到 System.Windows.Data Error: 24 : Both 'ItemContainerStyle' and 'ItemContainerStyleSelector' are set; 'ItemContainerStyleSelector' will be ignored.
,所以我假设 ItemContainerStyle 不是问题,就像我最初想的那样。
jstreet 指出,它与 MahApps.Metro 有关,但...(请参阅他的评论)
我当前的实现:
<DataGrid ItemsSource="{Binding Items}" ItemContainerStyleSelector="{StaticResource StyleSelector}">
样式选择器:
public class GridRowStyleSelector : StyleSelector
{
private readonly ResourceDictionary _dictionary;
public GridRowStyleSelector()
{
_dictionary = new ResourceDictionary
{
Source = new Uri(@"pack://application:,,,/myApp;component/View/GridResources.xaml")
};
}
public override Style SelectStyle(object item, DependencyObject container)
{
string name = item?.GetType().Name;
if (name != null && _dictionary.Contains(name))
{
return (Style)_dictionary[name];
}
return null;
}
}
GridResources.xaml 测试值:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="GridItem" TargetType="DataGridRow">
<Setter Property="BorderThickness" Value="3"/>
</Style>
<Style x:Key="GridSeparator" TargetType="DataGridRow">
<Setter Property="BorderBrush" Value="Red"/>
</Style>
</ResourceDictionary>
您可以通过明确将其设置为 null
来覆盖默认值 ItemContainerStyle
:
<DataGrid ItemsSource="{Binding Items}"
ItemContainerStyle="{x:Null}"
ItemContainerStyleSelector="{StaticResource StyleSelector}">
GridRowStyleSelector 的构造函数class 是静态和私有的。 尝试从此 class 中删除 'static' 关键字,并使构造函数 public.
我想我找到了罪魁祸首。结果表明,在 DataGrid
中处理行样式的正确方法是通过 RowStyle
和 RowStyleSelector
属性,而不是 ItemContainerStyle
和 ItemContainerStyleSelector
。它们可以工作,但只有在您明确使用 RowStyle
或 RowStyleSelector
时才会起作用。这正是 MahApps Metro 所做的 - 它设置 RowStyle
值(我相信通过覆盖 DataGrid
默认样式)。然后我认为 ItemContainerStyle
是由 DataGrid
内部设置的(一些测试显示 ItemContainerStyle
已设置,尽管明确将其设置为 null
)。
总而言之,这应该可以解决您的问题:
<DataGrid ItemsSource="{Binding Items}"
RowStyle="{x:Null}"
RowStyleSelector="{StaticResource StyleSelector}">
(...)
</DataGrid>
此外,要修改 MahApps 行样式而不是完全丢弃它,您应该将您的样式基于 MahApps 行样式:
<Style x:Key="GridItem" TargetType="DataGridRow"
BasedOn="{StaticResource MetroDataGridRow}">
<Setter Property="BorderThickness" Value="3"/>
</Style>
<Style x:Key="GridSeparator" TargetType="DataGridRow"
BasedOn="{StaticResource MetroDataGridRow}">
<Setter Property="BorderBrush" Value="Red"/>
</Style>