DevExpress的GridControl控件绑定动态数据时列排序问题解决
程序员文章站
2022-03-04 11:50:26
...
GridControl是一个表格组件,可以格式化显示结构数据。其基本使用方法如下:
在上述例子中,GridControl的列在xaml文件里已经设定,顺序是排好的。当GridControl的控件在cs文件定义,通过binding进行绑定的时候,序列就会按照对象属性定义的先后进行排列了。这就带来一个问题。比如基类A定义了两个属性A1和A2,继承基类A的类B定义了两个属性B1和B2。当我们将B的实例绑定到视图中的GridControl时,显示的顺序是A1,A2,B1,B2。而我们希望的顺序是B1,A1,B2,A2,这个问题怎么处理呢?
问题解决主要包含以下步骤:
1)定义两个类:A和B
2)将类B的实例与GridControl绑定
3)定义GridControl列排序xml文件
4)读取上述xml文件,将该排序定义绑定到GridControl
具体过程:
1)定义两个类:A和B
2)将类B的实例与GridControl绑定
viewmodel(Bviewmodel.cs)如下:
xaml(BModel.xaml)文件定义如下:
3)定义GridControl列排序xml文件
order.xml:
[code] <?xml version="1.0" standalone="yes"?>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="PenderOrder" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="B_order">
<xs:complexType>
<xs:sequence>
<xs:element name="B1" msdata:ReadOnly="true" msdata:Caption="B属性1" type="xs:string" minOccurs="0" />
<xs:element name="A属性1" msdata:ReadOnly="true" msdata:Caption="证券代码" type="xs:string" minOccurs="0" />
<xs:element name="B2" msdata:ReadOnly="true" msdata:Caption="B属性2" type="xs:string" minOccurs="0" />
<xs:element name="A2" msdata:ReadOnly="true" msdata:Caption="A属性2" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>[/code]
4)读取上述xml文件,将该排序定义绑定到GridControl
定义读取xml通用函数:
定义列信息:
修改viewmodel,添加列排序定义字段并在构造函数中读取xml:
在xaml中绑定列排序定义:
<dxg:GridControl x:Name="grid" CustomUnboundColumnData="grid_CustomUnboundColumnData">
<dxg:GridControl.Columns>
<dxg:GridColumn FieldName="Number1" />
<dxg:GridColumn FieldName="Number2" />
<dxg:GridColumn FieldName="Text1" />
<dxg:GridColumn FieldName="Text2" />
</dxg:GridControl.Columns>
<dxg:GridControl.View>
<dxg:TableView x:Name="view" AutoWidth="True" CellValueChanged="view_CellValueChanged" />
</dxg:GridControl.View>
</dxg:GridControl>
在上述例子中,GridControl的列在xaml文件里已经设定,顺序是排好的。当GridControl的控件在cs文件定义,通过binding进行绑定的时候,序列就会按照对象属性定义的先后进行排列了。这就带来一个问题。比如基类A定义了两个属性A1和A2,继承基类A的类B定义了两个属性B1和B2。当我们将B的实例绑定到视图中的GridControl时,显示的顺序是A1,A2,B1,B2。而我们希望的顺序是B1,A1,B2,A2,这个问题怎么处理呢?
问题解决主要包含以下步骤:
1)定义两个类:A和B
2)将类B的实例与GridControl绑定
3)定义GridControl列排序xml文件
4)读取上述xml文件,将该排序定义绑定到GridControl
具体过程:
1)定义两个类:A和B
namespace com.test{
public class A
{
public string A1{get;set;}
public string A2{get;set;}
}
}
namespace com.test{
public class B:A
{
public string B1{get;set;}
public string B2{get;set;}
}
}
2)将类B的实例与GridControl绑定
viewmodel(Bviewmodel.cs)如下:
namespace com.test{
public class Bviewmodel: INotifyPropertyChanged
{
//应该在构造函数为该集合赋一些测试数据
private ObservableCollection<B> b_vm= new ObservableCollection<B>();
}
public ObservableCollection<B> B_vm
{
get { return this.b_vm; }
set { this.b_vm= value; }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyname)
{
PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
}
xaml(BModel.xaml)文件定义如下:
<UserControl x:Class="com.test.BModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:com.test"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:dxit="http://schemas.devexpress.com/winfx/2008/xaml/core/internal"
xmlns:syscommon="clr-namespace:HTSys.Brokerage.SysCommon.DataConfig;assembly=HTSys.Brokerage.SysCommon"
mc:Ignorable="d"
d:DesignHeight="384" d:DesignWidth="612">
<UserControl.DataContext>
<local:Bviewmodel />
</UserControl.DataContext>
<Grid>
<dxg:GridControl AutoGenerateColumns="None" ItemsSource="{Binding B_vm}" AllowLiveDataShaping="True">
<dxg:GridControl.View>
<dxg:TableView AllowPerPixelScrolling="True" ShowTotalSummary="True" ShowGroupPanel="False" ShowFocusedRectangle="True" AllowEditing="False"/>
</dxg:GridControl.View>
</dxg:GridControl>
</Grid>
</UserControl>
3)定义GridControl列排序xml文件
order.xml:
[code] <?xml version="1.0" standalone="yes"?>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="PenderOrder" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="B_order">
<xs:complexType>
<xs:sequence>
<xs:element name="B1" msdata:ReadOnly="true" msdata:Caption="B属性1" type="xs:string" minOccurs="0" />
<xs:element name="A属性1" msdata:ReadOnly="true" msdata:Caption="证券代码" type="xs:string" minOccurs="0" />
<xs:element name="B2" msdata:ReadOnly="true" msdata:Caption="B属性2" type="xs:string" minOccurs="0" />
<xs:element name="A2" msdata:ReadOnly="true" msdata:Caption="A属性2" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>[/code]
4)读取上述xml文件,将该排序定义绑定到GridControl
定义读取xml通用函数:
namespace com.test
{
/// <summary>
/// 视图的grid列设置
/// </summary>
public class GridSettingCommon
{
private string moduleName;
private string viewName;
/// <summary>
/// grid所在模块名称,用以区分同一grid在不同模块中的显示情况
/// </summary>
public string ModuleName
{
get { return this.moduleName; }
set { this.moduleName = value; }
}
/// <summary>
/// grid所在视图名称
/// </summary>
public string ViewName
{
get { return this.viewName; }
set { this.viewName = value; }
}
public GridSettingCommon(string moduleName, string viewName)
{
this.moduleName = moduleName;
this.viewName = viewName;
}
/// <summary>
/// 依据用户ID,获取对应设置
/// </summary>
/// <param name="userID"></param>
/// <returns></returns>
public List<GridColumInfoCommon> GetGridSettingByName(string xmpPath, string userID = "0", bool isTest = true)
{
DataTable dt = this.GetGridSettingDataTable(xmpPath);
List<GridColumInfoCommon> columnInfoList = new List<GridColumInfoCommon>();
if (isTest)
{
if (dt != null && dt.Columns.Count > 0)
{
int i = 0;
foreach (DataColumn col in dt.Columns)
{
GridColumInfoCommon gridColumn = new GridColumInfoCommon();
gridColumn.FieldName = col.ColumnName;
gridColumn.Header = col.Caption;
gridColumn.VisibleIndex = i++;
columnInfoList.Add(gridColumn);
}
}
}
return columnInfoList;
}
private DataTable GetGridSettingDataTable(string xmpPath, bool isTest = true)
{
DataTable dt = new DataTable();
try
{
if (isTest) {
string path = this.GetSchemaName(xmpPath);
dt.ReadXmlSchema(path);
}
}
catch (Exception ex)
{
//System.Windows.MessageBox.Show("获取配置信息失败!错误原因:" + ex.Message);
}
return dt;
}
private string GetSchemaName(string xmpPath,bool isTest = true)
{
string schemaName = string.Empty;
if (isTest)
{
//if (viewName == "StockQuotationByPosition")
schemaName = AppDomain.CurrentDomain.BaseDirectory + xmpPath;
}
return schemaName;
}
}
}
定义列信息:
namespace com.test
{
public class GridColumInfoCommon
{
public string Header { get; set; }
public string FieldName { get; set; }
public string BindingPath { get; set; }
public int VisibleIndex
{
get;
set;
}
}
public class ColumnInfoBehaviorCommon : Behavior<GridColumn>
{
public static readonly DependencyProperty ColumnInfoProperty =
DependencyProperty.RegisterAttached("ColumnInfoCommon", typeof(GridColumInfoCommon), typeof(ColumnInfoBehaviorCommon), new PropertyMetadata(null, OnColumnInfoChanged));
public static GridColumInfoCommon GetColumnInfoCommon(DependencyObject obj)
{
return (GridColumInfoCommon)obj.GetValue(ColumnInfoProperty);
}
public static void SetColumnInfoCommon(DependencyObject obj, GridColumInfoCommon value)
{
obj.SetValue(ColumnInfoProperty, value);
}
static void OnColumnInfoChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
GridColumn c = o as GridColumn;
if (e.NewValue != null)
Interaction.GetBehaviors(c).Add(new ColumnInfoBehaviorCommon() { Info = (GridColumInfoCommon)e.NewValue });
}
public static readonly DependencyProperty InfoProperty =
DependencyProperty.Register("Info", typeof(GridColumInfoCommon), typeof(ColumnInfoBehaviorCommon),
new PropertyMetadata(null, (d, e) => ((ColumnInfoBehaviorCommon)d).OnInfoChanged()));
public GridColumInfoCommon Info
{
get { return (GridColumInfoCommon)GetValue(InfoProperty); }
set { SetValue(InfoProperty, value); }
}
void OnInfoChanged()
{
if (Info == null) return;
if (AssociatedObject == null) return;
if (Info.FieldName != null)
AssociatedObject.FieldName = Info.FieldName;
if (Info.BindingPath != null)
AssociatedObject.Binding = new Binding() { Path = new PropertyPath(Info.BindingPath) };
}
protected override void OnAttached()
{
base.OnAttached();
OnInfoChanged();
}
}
public class ColumnTemplateSelectorCommon : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
GridColumnInfo column = (GridColumnInfo)item;
return (DataTemplate)((Control)container).FindResource("DefaultColumnTemplate");
}
}
}
修改viewmodel,添加列排序定义字段并在构造函数中读取xml:
namespace com.test{
public class Bviewmodel: INotifyPropertyChanged
{
//应该在构造函数为该集合赋一些测试数据
private ObservableCollection<B> b_vm= new ObservableCollection<B>();
private ObservableCollection<GridColumInfoCommon> bColumns = new ObservableCollection<GridColumInfoCommon>();
public Bviewmodel()
{
GridSettingCommon gridSettingCommon = new GridSettingCommon("test", "test");
List<GridColumInfoCommon> columnListB = gridSettingCommon.GetGridSettingByName("order.xml");
if (columnListB != null)
{
foreach (GridColumInfoCommon columnInfoCommon in columnListB )
this.bColumns.Add(columnInfoCommon);
columnListB.Clear();
}
}
public ObservableCollection<B> B_vm
{
get { return this.b_vm; }
set { this.b_vm= value; }
}
public ObservableCollection<GridColumInfoCommon> BColumns
{
get { return this.bColumns ; }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyname)
{
PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
}
在xaml中绑定列排序定义:
<UserControl x:Class="com.test.BModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:com.test"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:dxit="http://schemas.devexpress.com/winfx/2008/xaml/core/internal"
xmlns:syscommon="clr-namespace:HTSys.Brokerage.SysCommon.DataConfig;assembly=HTSys.Brokerage.SysCommon"
mc:Ignorable="d"
d:DesignHeight="384" d:DesignWidth="612">
<UserControl.DataContext>
<local:Bviewmodel />
</UserControl.DataContext>
<Grid>
<dxg:GridControl AutoGenerateColumns="None" ItemsSource="{Binding B_vm}" ColumnsSource="{Binding BColumns}" AllowLiveDataShaping="True">
<dxg:GridControl.ColumnGeneratorStyle>
<Style TargetType="dxg:GridColumn">
<Setter Property="Header" Value="{Binding Header}" />
<Setter Property="com.test:ColumnInfoBehaviorCommon.ColumnInfoCommon" Value="{Binding DataContext, RelativeSource={RelativeSource Mode=Self}}" />
<Setter Property="VisibleIndex" Value="{Binding Path=(dxit:DependencyObjectExtensions.DataContext).VisibleIndex, RelativeSource={RelativeSource Self}}" />
</Style>
</dxg:GridControl.ColumnGeneratorStyle>
<dxg:GridControl.View>
<dxg:TableView AllowPerPixelScrolling="True" ShowTotalSummary="True" ShowGroupPanel="False" ShowFocusedRectangle="True" AllowEditing="False"/>
</dxg:GridControl.View>
</dxg:GridControl>
</Grid>
</UserControl>
下一篇: C#中WinForm程序退出方法