Выбор стиля WPF DataGrid для строк

Я пытаюсь использовать ItemContainerStyleSelector для отображения различных стилей строк в сетке данных в зависимости от типа объекта, определяющего строку (ItemsSource представляет собой набор IGridItem, есть GridItem и GridSeparator, которые должны получить разные стили). моя проблема заключалась в том, что SelectStyle моего StyleSelector никогда не вызывался. Теперь я обнаружил (здесь), что проблема может заключаться в унаследованном стиле (библиотека MahApps Metro переопределяет стили по умолчанию всех стандартных элементов управления), который, вероятно, уже устанавливает ItemContainerStyle.

Итак, теперь мой вопрос: есть ли способ по-прежнему использовать мой StyleSelector, чтобы у меня был унаследованный стиль в качестве основы для выбранных стилей? А если нет, то как мне добиться другого стиля только для некоторых строк в зависимости от их типа объекта?

РЕДАКТИРОВАТЬ:
Установка ItemContainerStyle вручную на null не дала эффекта, SelectStyle моего StyleSelector по-прежнему никогда не вызывается.

EDIT2:
Поскольку я не получаю System.Windows.Data Error: 24 : Both 'ItemContainerStyle' and 'ItemContainerStyleSelector' are set; 'ItemContainerStyleSelector' will be ignored., как спрашивал Grx70, я предполагаю, что проблема не в 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>

person Florian Koch    schedule 27.04.2016    source источник
comment
Просто чтобы убрать это со стола - вы уверены, что {StaticResource StyleSelector} разрешается в экземпляр GridRowStyleSelector?   -  person Grx70    schedule 04.05.2016
comment
Сигнатура метода для стиля Select является общедоступным переопределением стиля SelectStyle (элемент объекта, контейнер DependencyObject)   -  person Manolo    schedule 04.05.2016
comment
Кроме того, вы получаете ошибку System.Windows.Data Error: 24 : Both 'ItemContainerStyle' and 'ItemContainerStyleSelector' are set; 'ItemContainerStyleSelector' will be ignored. в окне вывода?   -  person Grx70    schedule 04.05.2016
comment
@ Grx70 да, я знаю, что экземпляр разрешен, так как я могу сломать конструктор, и нет, я нигде не видел этой ошибки   -  person Florian Koch    schedule 04.05.2016
comment
@Маноло, я не знаю, что ты хочешь мне этим сказать, это именно то, что я реализовал   -  person Florian Koch    schedule 04.05.2016
comment
@ Grx70, но я только что заметил, что получаю "System.Reflection.TargetInvocationException" in mscorlib.dll каждый раз, когда перестраиваю содержимое сетки данных, содержащее GridSeparator - до сих пор не замечал этого, похоже, это связано   -  person Florian Koch    schedule 04.05.2016
comment
Действительно, метод StyleSelector.SelectStyle() вызывается в обычном приложении WPF, но не при использовании MahApps.Metro. Похоже, его вообще игнорируют. Кстати, никаких исключений в любом случае.   -  person jsanalytics    schedule 04.05.2016
comment
хорошо, спасибо за попытку, я отредактировал теги, чтобы включить Metro, возможно, кто-то, связанный с ним, увидит этот вопрос   -  person Florian Koch    schedule 04.05.2016


Ответы (3)


Кажется, я нашел виновника. Оказывается, правильный способ обработки стилей строк в 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>
person Grx70    schedule 04.05.2016

Вы можете переопределить значение по умолчанию ItemContainerStyle, явно установив для него значение null:

<DataGrid ItemsSource="{Binding Items}"
          ItemContainerStyle="{x:Null}"
          ItemContainerStyleSelector="{StaticResource StyleSelector}">
person Clemens    schedule 27.04.2016
comment
хорошо, я попробовал это, но я все еще никогда не останавливаюсь на SelectStyle... Кажется, что у моего селектора стилей есть еще одна причина, по которой его просто игнорируют:/ - person Florian Koch; 27.04.2016

Конструктор класса GridRowStyleSelector является статическим и закрытым. Попробуйте удалить "статические" ключевые слова из этого класса и сделать конструктор общедоступным.

person Manolo    schedule 04.05.2016
comment
Я до сих пор никогда не вхожу в SelectStyle... старый конструктор работает так же хорошо, как и нестатический, если я ставлю точку останова, он останавливается там - person Florian Koch; 04.05.2016