DXGrid меняет цвет сетки ряда DevExpress WPF

У меня есть юридическое лицо IsRemoved, Когда это станет правдой, сетка должна стать серой.

Для этого я использую этот код:

    <dxg:TableView.RowStyle>
        <Style TargetType="{x:Type dxg:GridRowContent}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding DataContext.IsRemoved, Mode=OneWay}" Value="True">
                    <Setter Property="Background" Value="Gray" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </dxg:TableView.RowStyle>
</dxg:TableView>

Но он будет работать только тогда, когда сетка показывает в первый раз. Я хочу изменить цвет, когда значение меняется. Недвижимость реализует INotifyPropertyChange Событие.

3 ответа

Примечание: этот ответ является устаревшим (см. Мой другой ответ).

Этот ответ предназначен для версий DevExpress до v14.1 или DevExpress версии 14.1 и после с UseLightweightTemplates="None",

Вам нужно иметь начальный установщик для свойства, которое вы хотите изменить. Это связано с порядком, в котором WPF использует стили.

Добавьте эту строку после тега стиля:

<Setter Property="Background" Value="Black" />

Полный пример:

<dxg:TableView.RowStyle>
    <Style TargetType="{x:Type dxg:GridRowContent}">
        <Setter Property="Background" Value="Black" />
        <Style.Triggers>
            <DataTrigger Binding="{Binding DataContext.IsRemoved, Mode=OneWay}" Value="True">
                <Setter Property="Background" Value="Gray" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</dxg:TableView.RowStyle>   

Начиная с версии 14.1 DevExpress, они представили Оптимизированный режим, который использует облегченные шаблоны. Это делает все быстрее, но требует изменения того, как указаны стили и DataTriggers.

Легкие шаблоны контролируются прикрепленным свойством UseLightweightTemplates="Row", который включен по умолчанию. Можно переключить на None для обратной совместимости.

Вот рабочий пример MVVM, как покрасить строку, если IsDirty свойство устанавливается для любой строки сетки.

<dxg:GridControl x:Name="MyGridControl"
        ItemsSource ="{Binding MyViewModelList}" 
        SelectionMode="None"
        VerticalAlignment="Stretch">
    <dxg:GridControl.Resources>
        <SolidColorBrush x:Key="GridRowIsDirty" Color="#FF602D2D" />
    </dxg:GridControl.Resources>
    <dxg:GridControl.View>
        <dxg:TableView UseLightweightTemplates="Row" >
            <dxg:TableView.RowStyle>
                <Style TargetType="dxg:RowControl">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Row.IsDirty}" Value="True">
                            <Setter Property="Background" Value="{StaticResource GridRowIsDirty}" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </dxg:TableView.RowStyle>
        </dxg:TableView>
    </dxg:GridControl.View>
    <dxg:GridControl.Columns>
        <dxg:GridColumn x:Name="Included" FieldName="Included"/>
        <dxg:GridColumn x:Name="ColumnB" Header="Column B" FieldName="ColumnB" ReadOnly="True"/>
        <dxg:GridColumn x:Name="ColumnC" Header="Column C" FieldName="ColumnC" ReadOnly="True"/>ReadOnly="True"/>
    </dxg:GridControl.Columns>
</dxg:GridControl>

В ViewModel за этой сеткой:

public ObservableCollection<MyViewModel> MyViewModelList { get; set; }

Каждая строка в сетке указывает на класс типа MyViewModel, который содержит пользовательский флаг IsDirty, который мы можем установить по требованию:

public bool IsDirty
{
    get { return _isDirty; }
    set
    {
        _isDirty = value;
        OnPropertyChanged();
    }
}

Приложение A: Дополнительные ссылки

Приложение B: Другие решения

Это также работает большую часть времени, но не будет работать, если источником события является контекстное меню, поэтому это не рекомендуется:

 <DataTrigger Binding="{Binding DataContext.IsDirty}" Value="True">
    <Setter Property="Background" Value="{StaticResource GridRowIsDirty}" />
 </DataTrigger>

Приложение C: AllowLiveDataShaping

Если триггер не срабатывает, попробуйте включить AllowLiveDataShaping="True" в <GridControl>, Однако старайтесь избегать этого, так как (теоретически) это влияет на скорость больших, сложных сеток (это не оказывает заметного влияния на большинство сеток разумного размера).

Приложение D: если ничего не помогает, используйте пользовательский шаблон ControlTemplate

С введением "UseLightweightTemplates" DevExpress сосредоточился на скорости. Однако методы, используемые для скорости, включают в себя отключение привязок, которые могут замедлить работу.

Это означает, что если мы что-то изменим в ячейке DxGrid, значение в ViewModel не изменится, пока пользователь не перейдет к следующей ячейке или строке. Это означает, что ViewModel отстает от того, что на самом деле находится в сетке.

Чтобы исправить это, единственное решение, которое я смог найти, - полностью обойти шаблоны DevExpress и использовать свои собственные. Это означает, что у DxGrid нет другого выбора, кроме как отображать пользовательский шаблон, который мгновенно обновляет ViewModel, как только пользователь его редактирует, а это означает, что цвет строки изменяется немедленно:

 <dxg:GridControl Grid.Row="3" x:Name="TrsGridControl"
        ItemsSource ="{Binding MyObservableCollection}"                             
        VerticalAlignment="Stretch"
        AllowLiveDataShaping ="True">
    <dxg:GridControl.Resources>
        <converter:TestConverter x:Key="TestConverter" />
        <ControlTemplate x:Key="DisplayedOnTicketTrs">
                <dxe:CheckEdit x:Name="DisplayedOnTicketCheckEdit" HorizontalAlignment="Center" IsChecked="{Binding RowData.Row.DisplayedOnTicket, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
         </ControlTemplate>
    </dxg:GridControl.Resources>
    <dxg:GridControl.View>
        <dxg:TableView UseLightweightTemplates="All"/>
    </dxg:GridControl.View>
    <dxg:GridControl.Columns>            
        <dxg:GridColumn x:Name="DisplayedOnTicketTrs" DisplayTemplate="{StaticResource DisplayedOnTicketTrs}" Header="Displayed On Ticket?" HeaderToolTip="Displayed On Ticket?" AllowEditing="False"/>
                        Header ="Displayed On Ticket?"/>
        <dxg:GridColumn x:Name="ColumnA" Header="ColumnA" FieldName="ColumnA" ReadOnly="True"/>
        <dxg:GridColumn x:Name="ColumnB" Header="ColumnB" FieldName="ColumnB" ReadOnly="True"/>            
    </dxg:GridControl.Columns>
 </dxg:GridControl>

После того, как я сделал это изменение, все начало работать:

  • Когда флажок установлен, цвет фона меняется мгновенно (если мы добавим триггер для изменения цвета фона, выше).
  • Редактирование DxGrid изменяет ViewModel мгновенно.
  • Изменение ViewModel обновляет DxGrid мгновенно.
  • Если ContextMenu обновляет ViewModel, то все просто работает.

Вы должны написать просто "Row" вместо "DataContext"

Другие вопросы по тегам