首页 > 代码库 > WPF报表自定义通用可筛选列头-WPF特工队内部资料

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 = http://www.mamicode.com/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("<ColumnDefinition Width=\"1\" />");                }                //添加一个标题的显示内容列,并设置固定宽度                sbStr.AppendLine(String.Format("<ColumnDefinition Width=\"{0}*\"/>", column.Width));                index++;            }        }        /// <summary>        /// 设置标题内容        /// </summary>        /// <param name="sbStr"></param>        /// <param name="column">当前列</param>        /// <param name="totalcolumnCount">总列数</param>        /// <param name="colIndex">内容索引列</param>        private static void SetContentPresenter(StringBuilder sbStr, ColumnItem column, int totalcolumnCount, ref int colIndex)        {            //计算出当前列所占的Grid的ColumnDefinition数目            int columnOffset = column.LastLevelColumnCount() * 2 - 1;            //计算当前列在整个标题中的标题行深度            int LevelDepth = column.Parent.ChildLevelDepth();            //用于控制绘制标题内容下面显示下线,以及当前显示标题的Grid.RowSpan            int rowOffset;  //一般情况默认为1            if (column.Columns.Count == 0)//            {                rowOffset = LevelDepth * 2 - 1;            }            else            {                rowOffset = 1; //            }            //计算出当前标题在第几个RowDefinition画内容下边线            int lineRow = (column.Level * 2 + 1) + (rowOffset - 1);              //计算出当前标题在第几个ColumnDefinition画内容右边线            int lineColumn = (colIndex + 1) + (columnOffset - 1);            //画标题,并设置当前标题在Grid中的定位            sbStr.AppendLine(                CreateDataGridTemplateColumnHeaderContent(                    String.IsNullOrWhiteSpace(column.ExtendName) ? column.Name : column.ExtendName,  //标题显示内容                    column.Level * 2,  //所属行,标题内容显示的Grid.Row                    rowOffset,  //标题内容显示的Grid.RowSpan                    colIndex,  //标题内容显示的Grid.Column列                    columnOffset //标题内容显示的Grid.ColumnSpan                ));            //存在子级,时添加下线            if (column.Columns.Count > 0)            {                sbStr.AppendLine(String.Format("<Rectangle Fill=\"#FFC9CACA\" VerticalAlignment=\"Stretch\" Height=\"1\" Grid.Row=\"{0}\" Grid.Column=\"{1}\" Grid.RowSpan=\"{2}\" Grid.ColumnSpan=\"{3}\" />", lineRow, colIndex, 1, columnOffset));            }            //标题右侧下线            if (lineColumn < (totalcolumnCount * 2 - 1))            {                sbStr.AppendLine(String.Format("<Rectangle Fill=\"#FFC9CACA\" VerticalAlignment=\"Stretch\" Width=\"1\" Visibility=\"Visible\" Grid.Row=\"{0}\" Grid.Column=\"{1}\" Grid.RowSpan=\"{2}\" Grid.ColumnSpan=\"{3}\" />", column.Level * 2, lineColumn, rowOffset, 1));            }            //存在子级,先从子级起画            if (column.Columns.Count > 0)            {                foreach (var item in column.Columns)                {                    SetContentPresenter(sbStr, item, totalcolumnCount, ref colIndex);                }            }            else            {                colIndex += 2; //含分隔线            }        }        /// <summary>        /// 设置单元格绑定        /// </summary>        /// <param name="sbStr"></param>        /// <param name="column"></param>        /// <param name="bindingParameter"></param>        /// <param name="index"></param>        private static void SetCellBinding(StringBuilder sbStr, ColumnItem column, bool bindingParameter, ref int index)        {            if (column.Columns.Count > 0)            {                foreach (var item in column.Columns)                {                    SetCellBinding(sbStr, item, bindingParameter, ref index);                }            }            else            {                if (index > 0)                {                    sbStr.AppendLine(String.Format("<Rectangle Fill=\"#FFC9CACA\" VerticalAlignment=\"Stretch\" Grid.Column=\"{0}\"/>", index));                    index++;                }                //构建指定类型的项绑定                IDataGridDataTemplateFactory templateFactory = ServiceFactory.GetService<IDataGridDataTemplateFactory>();                IDataGridDataTemplateService templateService = templateFactory.GetService(column.Type);                sbStr.AppendLine(templateService.CreateCellXaml(column, bindingParameter, index));                index++;            }        }        /// <summary>        /// 设置单元格列宽        /// </summary>        /// <param name="sbStr"></param>        /// <param name="column"></param>        /// <param name="index"></param>        private static void SetCellColumnDefinition(StringBuilder sbStr, ColumnItem column, ref int index)        {            if (column.Columns.Count > 0)            {                foreach (var item in column.Columns)                {                    SetCellColumnDefinition(sbStr, item, ref index);                }            }            else            {                if (index > 0)                {                    sbStr.AppendLine("<ColumnDefinition Width=\"1\" />");                }                sbStr.AppendLine(String.Format("<ColumnDefinition Width=\"{0}*\"/>", column.Width));                index++;            }        }        /// <summary>        /// 创建组列        /// </summary>        /// <param name="column"></param>        /// <param name="bindingParameter">是否是参数</param>        /// <returns></returns>        public static DataGridTemplateColumn CreateTemplateGroupColumn(ColumnItem column, bool bindingParameter)        {            var templateColumn = new DataGridTemplateColumn();            //当前列包含的子级深度            int LevelDepth = column.ChildLevelDepth();            //获取当前列子级的总列数            int totalcolumnCount = column.LastLevelColumnCount();    //            //设置当前列的宽度            templateColumn.Width = new DataGridLength(column.TotalGroupWidth() + LevelDepth);            //构建HeaderStyle以及CellTemplate模板            //动态构建标题样式 DataGridTemplateColumn.HeaderStyle            #region 构建多行标题            var sbHeaderStr = new StringBuilder();            sbHeaderStr.AppendLine("<Grid.RowDefinitions>");            for (int i = 0; i <= LevelDepth; i++)            {                if (i > 0)                {                    sbHeaderStr.AppendLine("<RowDefinition Height=\"1\" />");  //构建分割线,                }                if (i < LevelDepth)                {                    sbHeaderStr.AppendLine("<RowDefinition Height=\"25\" />");  //内容区域                }                else                {                    sbHeaderStr.AppendLine("<RowDefinition Height=\"*\" MinHeight=\"25\"/>"); //内容区域                }            }            sbHeaderStr.AppendLine("</Grid.RowDefinitions>");            sbHeaderStr.AppendLine("<Grid.ColumnDefinitions>");            int index = 0;            foreach (var item in column.Columns)            {                SetColumnDefinition(sbHeaderStr, item, ref index);            }            sbHeaderStr.AppendLine("</Grid.ColumnDefinitions>");            int columnOffset = totalcolumnCount * 2 - 1;            sbHeaderStr.AppendLine(CreateDataGridTemplateColumnHeaderContent(String.IsNullOrWhiteSpace(column.ExtendName) ? column.Name : column.ExtendName, -1, -1, -1, columnOffset));            sbHeaderStr.AppendLine(String.Format("<Rectangle Fill=\"#FFC9CACA\" VerticalAlignment=\"Stretch\" Height=\"1\" Grid.Row=\"1\" Grid.ColumnSpan=\"{0}\" />", columnOffset));            index = 0;            foreach (var item in column.Columns)            {                SetContentPresenter(sbHeaderStr, item, totalcolumnCount, ref index);            }            var headerStyleStr = HeaderStyleString();            headerStyleStr = headerStyleStr.Replace("{#content#}", sbHeaderStr.ToString());            templateColumn.HeaderStyle = (Style)XamlReader.Parse(headerStyleStr);            #endregion            //动态构建绑定DataTemplate DataGridTemplateColumn.CellTemplate            #region 构建多行标题数据绑定模板            var sbCellTempStr = new StringBuilder();            sbCellTempStr.AppendLine("<Grid.ColumnDefinitions>");            index = 0;            foreach (var item in column.Columns)            {                SetCellColumnDefinition(sbCellTempStr, item, ref index);            }            sbCellTempStr.AppendLine("</Grid.ColumnDefinitions>");            index = 0;            foreach (var item in column.Columns)            {                SetCellBinding(sbCellTempStr, item, bindingParameter, ref index);            }            var cellTemplateStr = CellDataTemplateString();            cellTemplateStr = cellTemplateStr.Replace("{#content#}", sbCellTempStr.ToString());            templateColumn.CellTemplate = (DataTemplate)XamlReader.Parse(cellTemplateStr);            #endregion            return templateColumn;        }        /// <summary>        /// 动态构建标题模板        /// </summary>        /// <param name="sbStr">目标结果</param>        /// <param name="title">标题名称</param>        /// <param name="row">所属Grid行Grid.Row</param>        /// <param name="rowSpan">所属合并行Grid.RowSpan</param>        /// <param name="column">所属Grid列Grid.Column</param>        /// <param name="columnSpan">所属合并列Grid.ColumnSpan</param>        private static String CreateDataGridTemplateColumnHeaderContent(String title, int row, int rowSpan, int column, int columnSpan)        {            StringBuilder sbStr = new StringBuilder();            sbStr.AppendLine("<ContentPresenter VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\"");            if (row > 0)            {                sbStr.AppendFormat(" Grid.Row=\"{0}\"", row);            }            if (rowSpan > 0)            {                sbStr.AppendFormat(" Grid.RowSpan=\"{0}\"", rowSpan);            }            if (column > 0)            {                sbStr.AppendFormat(" Grid.Column=\"{0}\"", column);            }            if (columnSpan > 0)            {                sbStr.AppendFormat(" Grid.ColumnSpan=\"{0}\"", columnSpan);            }            sbStr.Append(">");            sbStr.AppendLine("<ContentPresenter.Content>");            sbStr.AppendLine(String.Format("<TextBlock Text=\"{0}\" TextAlignment=\"Center\" TextWrapping=\"Wrap\" />", title));            sbStr.AppendLine("</ContentPresenter.Content>");            sbStr.AppendLine("</ContentPresenter>");            return sbStr.ToString();        }        /// <summary>        /// 创建单列        /// </summary>        /// <param name="column"></param>        /// <param name="bindingParameter"></param>        /// <returns></returns>        public static DataGridTemplateColumn CreateTemplateSingleColumn(ColumnItem column, bool bindingParameter)        {            if (column == null)            {                throw new ArgumentNullException("column");            }            if (String.IsNullOrWhiteSpace(column.BindingName))            {                throw new ArgumentNullException("column.BindingName", "末级列的绑定名称不能为 null 或空白字符串。");            }            //创建DataGrid的列            var templateColumn = new DataGridTemplateColumn();            //设置列的宽度            templateColumn.Width = new DataGridLength(column.Width);            //构建模板字符串            var sbStr = new StringBuilder();            //根据模板创建标题            sbStr.AppendLine(CreateDataGridTemplateColumnHeaderContent(String.IsNullOrWhiteSpace(column.ExtendName) ? column.Name : column.ExtendName, -1, -1, -1, -1));            //动态构建标题样式 DataGridTemplateColumn.HeaderStyle            #region DataGridTemplateColumn.HeaderStyle            var headerStyleStr = HeaderStyleString();            headerStyleStr = headerStyleStr.Replace("{#content#}", sbStr.ToString());            templateColumn.HeaderStyle = (Style)XamlReader.Parse(headerStyleStr);            sbStr.Clear();            #endregion            //动态构建绑定DataTemplate DataGridTemplateColumn.CellTemplate            #region DataGridTemplateColumn.CellTemplate            //构建绑定模板            IDataGridDataTemplateFactory templateFactory = ServiceFactory.GetService<IDataGridDataTemplateFactory>();            IDataGridDataTemplateService templateService = templateFactory.GetService(column.Type);            sbStr.AppendLine(templateService.CreateCellXaml(column, bindingParameter, null));            String cellTemplateStr = CellDataTemplateString();            cellTemplateStr = cellTemplateStr.Replace("{#content#}", sbStr.ToString());            templateColumn.CellTemplate = (DataTemplate)XamlReader.Parse(cellTemplateStr);            #endregion            return templateColumn;        }        #region 本地资源模板处理        private static object lockObj = new object();        private static String _HeaderStyleString = null;  //        private static String _CellDataTemplateString = null;//        /// <summary>        /// 获取标题样式        /// </summary>        /// <returns></returns>        public static String HeaderStyleString()        {            lock (lockObj)            {                if (_HeaderStyleString == null)                {                    _HeaderStyleString = GetResourceXamlString("HeaderStyle.xaml");                }                return _HeaderStyleString;            }        }        /// <summary>        /// 获取单元格模板字符串        /// </summary>        /// <returns></returns>        public static String CellDataTemplateString()        {            lock (lockObj)            {                if (_CellDataTemplateString == null)                {                    _CellDataTemplateString = GetResourceXamlString("CellDataTemplate.xaml");                }                return _CellDataTemplateString;            }        }        /// <summary>        /// 获取资源Xaml字符串        /// </summary>        /// <param name="fileName">文件名称</param>        /// <returns></returns>        private static String GetResourceXamlString(String fileName)        {            var res = Application.GetResourceStream(new Uri(String.Format("pack://application:,,,/TGP.DataGridDemo;component/Template/{0}", fileName), UriKind.RelativeOrAbsolute));            using (var sr = new StreamReader(res.Stream))            {                return sr.ReadToEnd();            }        }        #endregion    }

 

  源码下载

  

 

WPF报表自定义通用可筛选列头-WPF特工队内部资料