从 DevExpress v14.1 开始,他们引入了使用轻量级模板的优化模式。这使一切变得更快,但需要更改样式和 DataTriggers 的指定方式。
轻量级模板由附加属性控制UseLightweightTemplates="Row"
,默认情况下该属性处于启用状态。它可以切换到None
向后兼容。
IsDirty
这是一个有效的 MVVM 示例,说明如果为任何网格行设置了属性,如何为行着色。
<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; }
网格中的每一行都指向一个 type 类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,那么一切正常。