【问题标题】:WPF DataGrid StyleSelector for Rows行的 WPF DataGrid StyleSelector
【发布时间】:2016-08-21 05:42:05
【问题描述】:

我正在尝试使用 ItemContainerStyleSelector 根据定义行的对象的类型在数据网格中显示不同的行样式(ItemsSource 是IGridItems 的集合,有GridItemGridSeparator这应该得到不同的风格)。我的问题是,我的 StyleSelector 的 SelectStyle 从未被调用过。现在我发现 (here) 问题可能是继承样式(MahApps Metro 库重新定义了所有标准控件的默认样式),它可能已经设置了 ItemContainerStyle。

所以现在我的问题是:有没有办法仍然使用我的 StyleSelector,以便我将继承的样式作为所选样式的基础?如果没有,我如何根据对象类型为某些行实现不同的样式?

编辑:
手动将 ItemContainerStyle 设置为 null 没有效果,我的 StyleSelector 的 SelectStyle 仍然没有被调用。

EDIT2:
因为我没有像 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>

【问题讨论】:

  • 只是把它从桌面上拿下来 - 你确定 {StaticResource StyleSelector} 解析为 GridRowStyleSelector 实例吗?
  • Select 样式的方法签名是 public override Style SelectStyle(object item, DependencyObject container)
  • 此外,您是否在输出窗口中收到 System.Windows.Data Error: 24 : Both 'ItemContainerStyle' and 'ItemContainerStyleSelector' are set; 'ItemContainerStyleSelector' will be ignored. 错误?
  • @Grx70 是的,我知道实例已解决,因为我可以中断构造函数,不,我没有在任何地方看到该错误
  • 确实,StyleSelector.SelectStyle() 方法在常规 WPF 应用程序中被调用,但在使用 MahApps.Metro 时不会。看起来它被完全忽略了。顺便说一句,在任何一种情况下都没有例外。

标签: c# wpf mvvm mahapps.metro


【解决方案1】:

我想我找到了罪魁祸首。事实证明,在DataGrid 中处理行样式的正确方法是通过RowStyleRowStyleSelector 属性,而不是ItemContainerStyleItemContainerStyleSelector。它们有效,但只有在您明确使用RowStyleRowStyleSelector 之前。这正是 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>

【讨论】:

    【解决方案2】:

    您可以通过将默认的ItemContainerStyle 显式设置为null 来覆盖它:

    <DataGrid ItemsSource="{Binding Items}"
              ItemContainerStyle="{x:Null}"
              ItemContainerStyleSelector="{StaticResource StyleSelector}">
    

    【讨论】:

    • 好的,我试过了,但我仍然从不停留在SelectStyle...看来我的样式选择器还有另一个被忽略的理由:/
    【解决方案3】:

    GridRowStyleSelector 类的构造函数是静态的和私有的。 尝试从此类中删除“静态”关键字,并将构造函数公开。

    【讨论】:

    • 我仍然从不输入SelectStyle...旧的构造函数和非静态构造函数一样好用,如果我设置了一个断点,它就会停在那里
    猜你喜欢
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    • 2014-03-27
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    • 2015-08-03
    • 2012-10-04
    相关资源
    最近更新 更多