DataGrid控件可以选择手动声明要显示的字段与对应的标题,也可以绑定数据源后,自动生成列。
但自动模式下,列的标题是字段的名称,会生成数据源中所有的列。如果自动模式下需要进行某些判定与操作,这里展示一种可能有效的方法。
1、隐藏部分列
使用DataGrid的AutoGeneratingColumn事件,在生成列的时候过滤掉不需要的列。
前端:
<DataGrid>
ItemsSource="{Binding 数据源列表}"
AutoGenerateColumns="True"
AutoGeneratingColumn="gridWC_AutoGeneratingColumn" >
</DataGrid>
后台:
private void gridWC_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.Column.Header.ToString()=="字段一" || e.Column.Header.ToString() == "字段二" || e.Column.Header.ToString() == "字段三")
{
e.Cancel = true;
}
}
2、解释说明
DataGrid提供了两个与自动生成列有关的事件,分别是:
AutoGeneratingColumn:会在为每个属性创建列时引发,引发时列已经创建完毕,在这个事件中可以:
- 通过e.Column获取已经创建的列对象,并对其进行修改.
- 通过将e.Cancel设为true,以放弃该列.
- 如果不将e.Cancel设为true,则该事件后DataGrid会立刻将列加入列集合(Columns)中.
- 通过e.PropertyDescriptor可以知道当前是为什么属性在创建列,以及该属性的细节信息,包括属性所拥的Attribute集合.
AutoGeneratedColumns:会在为所有属性创建列完成时引发。
3、调整列的顺序
-
创建一个可以用在属性上的自定义Attribute,其包含一个值,用来表示为属性自动创建的列相对于所有列的位置.
-
在AutoGeneratingColumn事件中:
-
- 将e.Cancel设为true,使DataGrid认为所有自动创建的列都被取消(放弃)了.
-
- 通过e.PropertyDescriptor读取自定义的Attribute,从中取出位置信息.
-
- 将位置信息和列对象保存起来.
-
- 在AutoGeneratedColumns事件中对保存下来的列的集合进行排序,然后按顺序全部加入到DataGrid.Columns中
3.1 主要实现代码
internal class DemoViewModel
{
#region ColumnOrder
//使用 DataGridColumnOrderAttribute 设置自动生成列的顺序
//Use the DataGridColumnOrderAttribute to set the order in which columns are automatically generated
[DataGridColumnOrder(3)]
public string ColumnA { get; set; }
[DataGridColumnOrder(2)]
public bool ColumnB { get; set; }
[DataGridColumnOrder(1)]
public DateTime ColumnC { get; set; }
#endregion ColumnOrder
//使用 DisplayNameAttribute 设置自动生成列的显示名称
//Use DisplayNameAttribute to set the display name(Header) of the automatically generated column
[DisplayName("The DisplayName :)")]
public string ColumnD { get; set; }
//使用 DoNotAutoGenerateDataGridColumnAttribute 阻止自动生成列
//Block auto generate column with DoNotAutoGenerateDataGridColumnAttribute
[DoNotAutoGenerateDataGridColumn]
public string ColumnE { get; set; }
public static List<DemoViewModel> GetDemoList() => new List<DemoViewModel>()
{
new DemoViewModel()
{
ColumnA="DemoItem1",
ColumnB =true,
ColumnC =DateTime.Now
}
};
}
/// <summary>
/// 指定属性在System.Windows.Controls.DataGrid中自动生成列时,列的顺序
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class DataGridColumnOrderAttribute : Attribute
{
public static readonly DataGridColumnOrderAttribute Default = new DataGridColumnOrderAttribute(0);
public DataGridColumnOrderAttribute(int order)
{
DataGridColumnOrderValue = order;
}
public virtual int DataGridColumnOrder => DataGridColumnOrderValue;
protected int DataGridColumnOrderValue { get; set; }
public override bool Equals(object obj)
{
if (obj == this)
{
return true;
}
return obj is DataGridColumnOrderAttribute other && other.DataGridColumnOrder == DataGridColumnOrder;
}
public override int GetHashCode()
{
return DataGridColumnOrder.GetHashCode();
}
public override bool IsDefaultAttribute()
{
return Equals(Default);
}
}
public class DataGridEx : DataGrid
{
private List<ColumnAndOrder> _columnAndOrderList = new List<ColumnAndOrder>();
public DataGridEx()
{
AutoGeneratingColumn += DataGridEx_AutoGeneratingColumn;
AutoGeneratedColumns += DataGridEx_AutoGeneratedColumns;
}
private void DataGridEx_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
//将创建过程标记为已取消,以阻止DataGrid将生成的列对象加入到列集合中.
//Set event to cancel,DataGrid will not add current column to the Columns collection.
e.Cancel = true;
//从Attribute中读取显示名称.
//Read display name from Attribute.
var displayName = ((System.ComponentModel.MemberDescriptor)e.PropertyDescriptor).DisplayName;
if (!string.IsNullOrWhiteSpace(displayName))
{
e.Column.Header = displayName;
}
//从Attribute中读取顺序,以及是否自动生成列的标识.
//Read order from Attribute and whether to automatically generate column.
var attributes = ((System.ComponentModel.MemberDescriptor)e.PropertyDescriptor).Attributes;
var order = 0;
foreach (Attribute attribute in attributes)
{
if (attribute is DataGridColumnOrderAttribute orderAttribute)
{
order = orderAttribute.DataGridColumnOrder;
}
else if (attribute is DoNotAutoGenerateDataGridColumnAttribute)
{
//发现 DoNotAutoGenerateDataGridColumnAttribute 时,丢弃已生成的列
//Discard generated column when DoNotAutoGenerateDataGridColumnAttribute is found
return;
}
}
//将创建的列及顺序保存
//Save the column and order
_columnAndOrderList.Add(new ColumnAndOrder(order, e.Column));
}
private void DataGridEx_AutoGeneratedColumns(object sender, EventArgs e)
{
//按顺序将所有列加入到Columns集合中
//Add all columns to the Columns collection in order
foreach (var columnAndOrder in _columnAndOrderList.OrderBy(v => v.Order))
{
Columns.Add(columnAndOrder.DataGridColumn);
}
//不需要了
//No longer useful
_columnAndOrderList = null;
}
private class ColumnAndOrder
{
public ColumnAndOrder(int order, DataGridColumn dataGridColumn)
{
Order = order;
DataGridColumn = dataGridColumn;
}
public int Order { get; }
public DataGridColumn DataGridColumn { get; }
}
}