WPF界面应用开发技巧——绑定到条件格式规则的集合

下载DevExpress v20.2完整版

DevExpress WPF 拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。

使用模型视图ViewModel(MVVM)架构模型设计WPF应用程序时,可能需要在模型或视图模型中描述条件格式设置规则。 网格可以绑定到包含条件格式化规则的对象集合,这些条件在Model或ViewModel中进行了描述,从而最大限度地减少了“隐藏代码”的需求。

View模型实现

本文中使用的示例包含一个视图模型代码,其中包括以下类。

  • Order - 包含订单信息(例如数量,折扣等)的数据对象。
  • ViewModel - 订单视图模型,ViewModel公开Orders属性(在网格内显示的订单列表)和Rules属性(格式规则列表)。
  • OrderData - 提供要在网格控件中显示的订单信息。
  • FormattingRule - 描述条件格式设置规则,此类提供的属性与所有类型的条件格式设置规则通用的设置相对应。
  • FormattingType - 枚举应用格式的可能类型。

C#

 

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace GridDemo {
// ... 
public class ViewModel {
public ViewModel() {
Orders = GetOrders();
Rules = GetFormattingRules();
}

private static List<FormattingRule> GetFormattingRules() {
var rules = new List<FormattingRule>();
rules.Add(new FormattingRule() {
Expression = "([UnitPrice] * [Quantity] * (1 - [Discount]) - [Freight]) < 0",
ApplyToRow = true,
Type = FormattingType.Background
});
rules.Add(new FormattingRule() {
FieldName = "Discount",
Expression = "[Discount] > 0",
ApplyToRow = false,
Type = FormattingType.Font
});
rules.Add(new FormattingRule() {
FieldName = "Discount",
Expression = "[Discount] > 0",
Type = FormattingType.Icon
});
return rules;
}

private static List<Order> GetOrders() {
List<Order> list = new List<Order>();
list.Add(new Order() { City = "Aachen", UnitPrice = 10, Quantity = 20, Discount = 0, Freight = 30.54 });
// ...
return list;
}

// A list of orders displayed within the grid control. 
public List<Order> Orders { get; private set; }

// A list of conditional formatting rules. 
public List<FormattingRule> Rules { get; private set; }
}

// Corresponds to an order items displayed within grid. 
public class Order {
public string City { get; set; }
public double Discount { get; set; }
public double Freight { get; set; }
public double Quantity { get; set; }
public double UnitPrice { get; set; }
}

public enum FormattingType { Icon, Font, Background }

public class FormattingRule {
public virtual bool ApplyToRow { get; set; }
public virtual string Expression { get; set; }
public virtual string FieldName { get; set; }
public virtual FormattingType Type { get; set; }
}
}

 

注意:如果在将格式条件集合分配给网格控件之后可能对其进行了更改,则它应实现INotifyCollectionChanged,以便网格中可以自动反映在视图模型内进行的更改。

格式化条件模板和选择器

GridControl基于条件格式模板生成条件格式。 创建多个模板,每种条件格式类型一个模板。 使用单个模板,您可以在无限数量的网格控件中创建无限数量的条件格式。 在此示例中,存在三种条件格式模板:FontFormat、BackgroundFormat和IconFormat。

为避免绑定到列属性时的性能问题,请使用dxci:DependencyObjectExtensions.DataContext附加属性。 请参见下面的示例。

XAML

 

<!---->
xmlns:dxci="http://schemas.devexpress.com/winfx/2008/xaml/core/internal"
<!---->
<DataTemplate x:Key="FontFormat">
<ContentControl>
<dxg:FormatCondition 
ApplyToRow="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).ApplyToRow, RelativeSource={RelativeSource Self}}"
Expression="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).Expression, RelativeSource={RelativeSource Self}}"
FieldName="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).FieldName, RelativeSource={RelativeSource Self}}">
<dxg:FormatCondition.Format>
<dx:Format FontWeight="Bold" />
</dxg:FormatCondition.Format>
</dxg:FormatCondition>
</ContentControl>
</DataTemplate>

 

要根据列的类型选择所需的模板,请使用模板选择器。 在此示例中,模板选择器由FormatConditionSelector类表示。

XAML

 

<Window
x:Class="GridDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:GridDemo"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxci="http://schemas.devexpress.com/winfx/2008/xaml/core/internal"
xmlns:dxt="http://schemas.devexpress.com/winfx/2008/xaml/core/themekeys"
Height="350"
Width="525"
mc:Ignorable="d"
Title="MainWindow">

<Window.DataContext>
<local:ViewModel />
</Window.DataContext>

<Grid>
<Grid.Resources>
<DataTemplate x:Key="FontFormat">
<ContentControl>
<dxg:FormatCondition 
ApplyToRow="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).ApplyToRow, RelativeSource={RelativeSource Self}}"
Expression="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).Expression, RelativeSource={RelativeSource Self}}"
FieldName="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).FieldName, RelativeSource={RelativeSource Self}}">
<dxg:FormatCondition.Format>
<dx:Format FontWeight="Bold" />
</dxg:FormatCondition.Format>
</dxg:FormatCondition>
</ContentControl>
</DataTemplate>
<DataTemplate x:Key="BackgroundFormat">
<ContentControl>
<dxg:FormatCondition 
ApplyToRow="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).ApplyToRow, RelativeSource={RelativeSource Self}}"
Expression="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).Expression, RelativeSource={RelativeSource Self}}"
FieldName="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).FieldName, RelativeSource={RelativeSource Self}}">
<dxg:FormatCondition.Format>
<dx:Format Background="LightPink" />
</dxg:FormatCondition.Format>
</dxg:FormatCondition>
</ContentControl>
</DataTemplate>
<DataTemplate x:Key="IconFormat">
<ContentControl>
<dxg:FormatCondition 
ApplyToRow="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).ApplyToRow, RelativeSource={RelativeSource Self}}"
Expression="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).Expression, RelativeSource={RelativeSource Self}}"
FieldName="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).FieldName, RelativeSource={RelativeSource Self}}">
<dxg:FormatCondition.Format>
<dx:Format Icon="{dx:IconSet Name=Stars3_1}" />
</dxg:FormatCondition.Format>
</dxg:FormatCondition>
</ContentControl>
</DataTemplate>
<local:FormatConditionSelector 
x:Key="selector"
BackgroundTemplate="{StaticResource BackgroundFormat}"
FontTemplate="{StaticResource FontFormat}"
IconTemplate="{StaticResource IconFormat}" />
</Grid.Resources>

</Grid>

</Window>

 

C#

 

public class FormatConditionSelector : DataTemplateSelector {
public override DataTemplate SelectTemplate(object item, DependencyObject container) {
if(!(item is FormattingRule)) return null;
var vm = item as FormattingRule;
switch(vm.Type) {
case FormattingType.Icon:
return IconTemplate;
case FormattingType.Font:
return FontTemplate;
case FormattingType.Background:
return BackgroundTemplate;
default: return null;
}
}

public DataTemplate BackgroundTemplate { get; set; }
public DataTemplate FontTemplate { get; set; }
public DataTemplate IconTemplate { get; set; }
}

 

注意:如果可以使用单个模板描述所有条件格式,则无需创建模板选择器。 而是,将此模板分配给网格视图的TableView.FormatConditionGeneratorTemplate (TreeListViewTreeListView.FormatConditionGeneratorTemplate)属性。

自定义GridControl

最后,指定网格视图的FormatConditionGeneratorTemplateSelector和FormatConditionsSource属性。TableView.FormatConditionsSourceTreeListView.FormatConditionsSource)属性指定网格生成条件格式的来源,TableView.FormatConditionGeneratorTemplateSelector (TreeListView.FormatConditionGeneratorTemplateSelector) 属性指定模板选择器,该选择器根据其类型为每种条件格式返回一个模板。

XAML

 

<dxg:GridControl 
AutoGenerateColumns="AddNew"
EnableSmartColumnsGeneration="True"
ItemsSource="{Binding Orders}">
<dxg:GridControl.View>
<dxg:TableView 
FormatConditionGeneratorTemplateSelector="{StaticResource selector}"
FormatConditionsSource="{Binding Rules}" />
</dxg:GridControl.View>
</dxg:GridControl>

 

下图显示了结果。

WPF界面应用开发技巧——绑定到条件格式规则的集合

上DevExpress中文网,获取第一手最新产品资讯!

DevExpress技术交流群3:700924826      欢迎一起进群讨论

WPF界面应用开发技巧——绑定到条件格式规则的集合

上一篇:PHP如何获取数组的最后一个元素


下一篇:MVC, MVP, MVVM