DXGrid如何更改行颜色:DevExpress WPF

3

我有一个属性为IsRemoved的实体。当它变成true时,网格行应该是灰色的。

为了实现这一点,我使用了以下代码:

    <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个回答

6
请注意:这个答案是旧版的(请参考我的其他答案)。本答案适用于DevExpress v14.1之前的版本,或者使用UseLightweightTemplates="None"的DevExpress v14.1及以后版本。
由于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>   

在我尝试这段代码之前,我的数据触发器根本不起作用。关键是要在.IsRemoved前缀中加上DataContext,而不是RowData.Row - Contango

2
从DevExpress的v14.1开始,他们引入了使用轻量级模板的优化模式。这使得一切都更快,但需要更改样式和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

如果触发器没有触发,请尝试在<GridControl>中开启AllowLiveDataShaping="True"。但是,尽量避免这样做,因为它(理论上)会影响大型复杂网格的速度(对于大多数合理大小的网格没有明显影响)。

附录 D:如果所有其他方法都失败了,请使用自定义ControlTemplate

随着DevExpress引入“UseLightweightTemplates”,他们一直在关注速度。然而,用于提高速度的技术涉及关闭可能减慢速度的绑定。

这意味着,如果我们更改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,则一切都可以正常工作。

1
非常详细的答案,正是我所需要的,因为我也有一个IsDirty属性! - rollsch

0

你应该写"Row"而不是"DataContext"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接