WPF报表自定义通用可筛选列头-WPF特工队内部资料
Posted 秋末#
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF报表自定义通用可筛选列头-WPF特工队内部资料相关的知识,希望对你有一定的参考价值。
由于项目需要制作一个可通用的报表多行标题,且可实现各种类型的内容显示,包括文本、输入框、下拉框、多选框等(自定的显示内容可自行扩展),并支持参数绑定转换,效果如下:
源码结构
ColumnItem类:对列的宽度,对象方式,显示类型,绑定名称,converter资源进行设置
/// <summary> /// 描述 <see cref="ColumnItem"/> 动态列项目,用于在后台构建多列标题绑定项 /// </summary> [Serializable] public sealed class ColumnItem : NotifyPropertyChangedBase, ICloneable { /// <summary> /// 实例化 <see cref="ColumnItem"/> 类新实例,一般用于顶级标题栏 /// </summary> /// <param name="name">默认列名</param> public ColumnItem(String name) : this(name, "") { } /// <summary> /// 实例化 <see cref="ColumnItem"/> 类新实例 /// </summary> /// <param name="name">默认列名</param> /// <param name="bindingName">绑定名称</param> public ColumnItem(String name, String bindingName) : this(name, bindingName, "", "", HorizontalAlignment.Left, 80) { } /// <summary> /// 实例化 <see cref="ColumnItem"/> 类新实例 /// </summary> /// <param name="name">默认列名</param> /// <param name="bindingName">绑定名称</param> /// <param name="converterResourceKey">绑定的资源键(传递此资源时,要在资源中声明)</param> /// <param name="stringFormat">字符串格式</param> /// <param name="alignment">对齐方式</param> /// <param name="width">列宽</param> /// <param name="visibility">是否显示</param> public ColumnItem(String name, String bindingName, String converterResourceKey, String stringFormat, HorizontalAlignment alignment, int width, Visibility visibility) : this(name, "", bindingName, converterResourceKey, stringFormat, alignment, width, visibility, ColumnType.TextBlock) { } /// <summary> /// 实例化 <see cref="ColumnItem"/> 类新实例 /// </summary> /// <param name="name">默认列名</param> /// <param name="bindingName">绑定名称</param> /// <param name="converterResourceKey">绑定的资源键(传递此资源时,要在资源中声明)</param> /// <param name="stringFormat">字符串格式</param> /// <param name="alignment">对齐方式</param> /// <param name="width">列宽</param> public ColumnItem(String name, String bindingName, String converterResourceKey, String stringFormat, HorizontalAlignment alignment, int width) : this(name, "", bindingName, converterResourceKey, stringFormat, alignment, width, Visibility.Visible, ColumnType.TextBlock) { } /// <summary> /// 实例化 <see cref="ColumnItem"/> 类新实例 /// </summary> /// <param name="name">默认列名</param> /// <param name="extendName">扩展列名</param> /// <param name="bindingName">绑定名称</param> /// <param name="converterResourceKey">绑定的资源键(传递此资源时,要在资源中声明)</param> /// <param name="stringFormat">字符串格式</param> /// <param name="alignment">对齐方式</param> /// <param name="width">列宽</param> public ColumnItem(String name, String extendName, String bindingName, String converterResourceKey, String stringFormat, HorizontalAlignment alignment, int width) : this(name, extendName, bindingName, converterResourceKey, stringFormat, alignment, width, Visibility.Visible, ColumnType.TextBlock) { } /// <summary> /// 实例化 <see cref="ColumnItem"/> 类新实例 /// </summary> /// <param name="name">默认列名</param> /// <param name="bindingName">绑定名称</param> /// <param name="converterResourceKey">绑定的资源键(传递此资源时,要在资源中声明)</param> /// <param name="stringFormat">字符串格式</param> /// <param name="alignment">对齐方式</param> /// <param name="width">列宽</param> /// <param name="columnType">数据模板内容类型</param> public ColumnItem(String name, String bindingName, String converterResourceKey, String stringFormat, HorizontalAlignment alignment, int width, ColumnType columnType) : this(name, "", bindingName, converterResourceKey, stringFormat, alignment, width, Visibility.Visible, columnType) { } /// <summary> /// 实例化 <see cref="ColumnItem"/> 类新实例 /// </summary> /// <param name="name">默认列名</param> /// <param name="extendName">扩展列名</param> /// <param name="bindingName">绑定名称</param> /// <param name="converterResourceKey">绑定的资源键(传递此资源时,要在资源中声明)</param> /// <param name="stringFormat">字符串格式</param> /// <param name="alignment">对齐方式</param> /// <param name="width">列宽</param> /// <param name="columnType">数据模板内容类型</param> public ColumnItem(String name, String extendName, String bindingName, String converterResourceKey, String stringFormat, HorizontalAlignment alignment, int width, Visibility visibility) : this(name, extendName, bindingName, converterResourceKey, stringFormat, alignment, width, visibility, ColumnType.TextBlock) { } /// <summary> /// 实例化 <see cref="ColumnItem"/> 类新实例 /// </summary> /// <param name="name">默认列名</param> /// <param name="extendName">扩展列名</param> /// <param name="bindingName">绑定名称</param> /// <param name="converterResourceKey">绑定的资源键(传递此资源时,要在资源中声明)</param> /// <param name="stringFormat">字符串格式</param> /// <param name="alignment">对齐方式</param> /// <param name="width">列宽</param> /// <param name="columnType">数据模板内容类型</param> public ColumnItem(String name, String extendName, String bindingName, String converterResourceKey, String stringFormat, HorizontalAlignment alignment, int width, ColumnType columnType) : this(name, extendName, bindingName, converterResourceKey, stringFormat, alignment, width, Visibility.Visible, columnType) { } /// <summary> /// 实例化 <see cref="ColumnItem"/> 类新实例 /// </summary> /// <param name="name">默认列名</param> /// <param name="extendName">扩展列名</param> /// <param name="bindingName">绑定名称</param> /// <param name="converterResourceKey">绑定的资源键(传递此资源时,要在资源中声明)</param> /// <param name="stringFormat">字符串格式</param> /// <param name="alignment">对齐方式</param> /// <param name="width">列宽</param> /// <param name="visibility">是否显示</param> /// <param name="columnType">数据模板内容类型</param> public ColumnItem(String name, String extendName, String bindingName, String converterResourceKey, String stringFormat, HorizontalAlignment alignment, int width, Visibility visibility, ColumnType columnType) { this.ID = Guid.NewGuid(); if (String.IsNullOrWhiteSpace(name)) { throw new ArgumentNullException("titleName", "标题不能为 null 或 空白字符串。"); } this.Name = name; this.ExtendName = extendName; this.BindingName = (String.IsNullOrWhiteSpace(bindingName)) ? "simple" : bindingName; this.ConverterResourceKey = converterResourceKey; this.StringFormat = stringFormat; this.Alignment = alignment; this.Width = width; this.Visibility = visibility; this.Type = columnType; this.Columns = new ColumnItemCollection(this); //初始化 this.Level = 0; //默认 this.TextWrapping = System.Windows.TextWrapping.NoWrap; } private Int32 mWidth; private Visibility mVisibility; private HorizontalAlignment mAlignment; public Guid ID { get; private set; } /// <summary> /// 列宽 /// </summary> public Int32 Width { get { return mWidth; } set { mWidth = value; OnPropertyChanged("Width"); } } /// <summary> /// 列显示 /// </summary> public Visibility Visibility { get { return mVisibility; } set { mVisibility = value; OnPropertyChanged("Visibility"); } } /// <summary> /// 获取或设置水平对齐方式 /// </summary> public HorizontalAlignment Alignment { get { return mAlignment; } set { mAlignment = value; OnPropertyChanged("Alignment"); } } /// <summary> /// 默认列名 /// </summary> public String Name { get; private set; } /// <summary> /// 扩展列名 /// </summary> public String ExtendName { get; set; } /// <summary> /// 绑定名称 /// </summary> public String BindingName { get; set; } /// <summary> /// 获取或设置转换资源键 /// </summary> public String ConverterResourceKey { get; set; } /// <summary> /// 获取或设置字符串格式 /// </summary> public String StringFormat { get; set; } /// <summary> /// 控件类型 /// </summary> public ColumnType Type { get; set; } /// <summary> /// 获取或设置是否自动换行(默认为 NoWrap) /// </summary> public TextWrapping TextWrapping { get; set; } public ColumnComboBox ColumnComboBox { get; set; } /// <summary> /// 获取列集合 /// </summary> public ColumnItemCollection Columns { get; private set; } /// <summary> /// 获取级别 /// </summary> public int Level { get; internal set; } /// <summary> /// 获取父级 /// </summary> public ColumnItem Parent { get; internal set; } /// <summary> /// 获取子级深度 /// </summary> /// <returns></returns> public int ChildLevelDepth() { if (this.Columns.Count > 0) { return this.CalcLevelDepth(true) - this.Level; } else { return 0; } } /// <summary> /// 计算获取级别深度 /// </summary> /// <param name="child">计算子级</param> /// <returns></returns> private int CalcLevelDepth(bool child) { if (this.Columns.Count > 0) { int level = this.Columns.Max(c => c.CalcLevelDepth(child)); if (child) { return level; } else { return level - this.Level; } } else { return this.Level; } } /// <summary> /// 获取当前列的所有最后子集的总数 /// </summary> /// <returns></returns> public int LastLevelColumnCount() { int value = 0; if (this.Columns.Count > 0) { value += this.Columns.Sum(c => c.LastLevelColumnCount()); } else { value = 1; } return value; } /// <summary> /// 合计总宽度 /// </summary> /// <returns></returns> public int TotalGroupWidth() { int value; if (this.Columns.Count > 0) { value = this.Columns.Sum(c => c.TotalGroupWidth()); } else { value = this.Width; } return value; } /// <summary> /// 验证(必须设置绑定值) /// </summary> internal void CreateVerify() { if (this.Columns.Count == 0) { if (String.IsNullOrWhiteSpace(this.BindingName)) { throw new ArgumentNullException(String.Format("{0} 为末级时,绑定路径 BindingPath 为 null 或空白字符串。", this.Name)); } } } public void SetColumnComboBox(ColumnComboBox columnComboBox) { this.ColumnComboBox = columnComboBox; } #region ICloneable ColumnItem 对象深度复制 public object Clone() { ColumnItem item = (ColumnItem)this.MemberwiseClone(); item.Parent = null; item.Name = this.Name; item.ExtendName = this.ExtendName; item.Columns = new ColumnItemCollection(item); foreach (var o in this.Columns) { var _o = (ColumnItem)o.Clone(); _o.Parent = null; item.Columns.Add(_o); } return item; } private void OnClone(ColumnItemCollection collection, ColumnItemCollection collection2) { foreach (var item in collection2) { var _o = (ColumnItem)item.Clone(); if (item.Columns.Count > 0) { OnClone(item.Columns, item.Columns); } collection.Add(_o); } } #endregion } [Serializable] public class ColumnComboBox : NotifyPropertyChangedBase { public ColumnComboBox(String comboBoxBindName) : this(comboBoxBindName, "", "", "") { } public ColumnComboBox(String comboBoxBindName, String selectedItemBindName) : this(comboBoxBindName, selectedItemBindName, "", "") { } public ColumnComboBox(String comboBoxBindName, String selectedItemBindName, String selectedValuePath, String displayMemberPath) { this.mComboBoxBindName = comboBoxBindName; this.mSelectedItemBindName = selectedItemBindName; this.mSelectedValuePath = selectedValuePath; this.mDisplayMemberPath = displayMemberPath; } private String mSelectedItemBindName; private String mComboBoxBindName; private String mSelectedValuePath = ""; private String mDisplayMemberPath = ""; private ObservableCollection<string> itemSource; // /// <summary> /// 绑定资源 /// </summary> public String ComboBoxBindName { get { return mComboBoxBindName; } set { mComboBoxBindName = value; } } /// <summary> /// 选中值 /// </summary> public string SelectedValuePath { get { return mSelectedValuePath; } set { mSelectedValuePath = value; } } /// <summary> /// 显示值 /// </summary> public string DisplayMemberPath { get { return mDisplayMemberPath; } set { mDisplayMemberPath = value; } } public string SelectedItemBindName { get { return mSelectedItemBindName; } set { mSelectedItemBindName = value; } } }
报表内容中需要其他类型时,扩展IDataGridDataTemplateService接口
/// <summary> /// <see cref="DataGrid"/>控件数据模板<see cref="DataTemplate"/>构建服务, /// 根据<see cref="DataTemplate"/>的内容多样性构建不同的显示控件,主要针对单一控件显示 /// </summary> public interface IDataGridDataTemplateService { /// <summary> /// 动态构内容绑定模板 /// </summary> /// <param name="column">自定义列信息</param> /// <param name="bindingParameter">是否参数转换</param> /// <param name="gridColum">绑定的子列索引 </param> /// <returns></returns> String CreateCellXaml(ColumnItem column, bool bindingParameter, int? gridColum); }
DataGridTemplateColumnHelper核心类,组织动态的列标题以及绑定列,可在下载源码参考。
/// <summary> /// 自定义模板列构建帮助类 /// </summary> internal static class DataGridTemplateColumnHelper { /// <summary> /// 设置标题Grid列宽度,组织出一个复杂的标题格式 /// </summary> /// <param name="sbStr">标题字符串</param> /// <param name="column">列</param> /// <param name="index">列索引,用于控制标题内容显示的边线</param> private static void SetColumnDefinition(StringBuilder sbStr, ColumnItem column, ref int index) { if (column.Columns.Count > 0) { foreach (var item in column.Columns) { SetColumnDefinition(sbStr, item, ref index); } } else //默认包含一列 { if (index > 0) //当index>0时,添加一个右侧的Rectangle矩形图形边线位置,默认是左侧和右侧是不绘制边线 { sbStr.AppendLine("WPF管理系统自定义分页控件 - WPF特工队内部资料WPF (DataGridColumnHeader)实现自义定列头样式 并绑定数据