• Silverlight多重表头实现


    效果:

      

    实现主要逻辑:通过动态拼接XML生成表头样式,绑定到列上。

    主要是动态拼接XML时要仔细核对对应的占位行,具体可以看代码,注释很详细

    两个类一个接口

    NTree<T>:定义表头树形结构

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Collections.ObjectModel;
      5 
      6 namespace SLDGHeader
      7 {
      8     /// <summary>
      9     /// 树结构
     10     /// </summary>
     11     /// <typeparam name="T">节点中的数据</typeparam>
     12     public class NTree<T>
     13     {
     14         /// <summary>
     15         /// 节点数据
     16         /// </summary>
     17         private readonly T data;
     18         /// <summary>
     19         /// 节点数据
     20         /// </summary>
     21         public T Data
     22         {
     23             get { return data; }
     24         }
     25         /// <summary>
     26         /// 是否根节点
     27         /// </summary>
     28         public bool IsRoot { get { return Parent == null; } }
     29         /// <summary>
     30         /// 当前节点深度
     31         /// 根节点为1
     32         /// </summary>
     33         public int Depth { get; private set; }
     34         /// <summary>
     35         /// 父节点
     36         /// </summary>
     37         public NTree<T> Parent
     38         {
     39             get;
     40             private set;
     41         }
     42         /// <summary>
     43         /// 子节点
     44         /// </summary>
     45         public ReadOnlyCollection<NTree<T>> Children
     46         {
     47             get { return children.AsReadOnly(); }
     48         }
     49         private List<NTree<T>> children;
     50         /// <summary>
     51         /// 实例化一个节点
     52         /// </summary>
     53         /// <param name="data">节点数据</param>
     54         public NTree(T data)
     55         {
     56             this.Depth = 1;
     57             this.data = data;
     58             children = new List<NTree<T>>();
     59         }
     60         /// <summary>
     61         /// 在当前节点添加子节点
     62         /// </summary>
     63         /// <param name="data">节点数据</param>
     64         /// <returns>当前节点</returns>
     65         public NTree<T> AddChild(T data)
     66         {
     67             var node = new NTree<T>(data) { Parent = this, Depth = this.Depth + 1 };
     68             children.Add(node);
     69             return this;
     70         }
     71         /// <summary>
     72         /// 在当前节点子节点中插入子节点
     73         /// </summary>
     74         /// <param name="index">插入位置</param>
     75         /// <param name="data">节点数据</param>
     76         /// <returns>当前节点</returns>
     77         public NTree<T> InsertChild(int index, T data)
     78         {
     79             var node = new NTree<T>(data) { Parent = this, Depth = this.Depth + 1 };
     80             children.Insert(index, node);
     81             return this;
     82         }
     83         /// <summary>
     84         /// 在当前节点添加子节点
     85         /// </summary>
     86         /// <param name="data">节点数据</param>
     87         /// <returns>当前节点</returns>
     88         public NTree<T> AddChilren(params T[] datas)
     89         {
     90             foreach (var data in datas)
     91             {
     92                 AddChild(data);
     93             }
     94             return this;
     95         }
     96         /// <summary>
     97         /// 移除当前节点下指定的子节点
     98         /// </summary>
     99         /// <param name="node">要移除的子节点</param>
    100         /// <returns>当前节点</returns>
    101         public NTree<T> RemoveChild(NTree<T> node)
    102         {
    103             children.Remove(node);
    104             return this;
    105         }
    106         /// <summary>
    107         /// 在当前节点添加兄弟节点
    108         /// </summary>
    109         /// <param name="data">节点数据</param>
    110         /// <returns>当前节点</returns>
    111         /// <exception cref="NullParentNodeException:当前节点没有父节点">当前节点没有父节点</exception>
    112         public NTree<T> AddBrother(T data)
    113         {
    114             if (this.Parent == null)
    115             {
    116                 throw new NullParentNodeException("有父节点的节点才能添加兄弟节点。");
    117             }
    118 
    119             this.Parent.AddChild(data);
    120             return this;
    121         }
    122         /// <summary>
    123         /// 获取指定索引处的子节点
    124         /// </summary>
    125         /// <param name="i">子节点索引</param>
    126         /// <returns>子节点</returns>
    127         /// <exception cref="ArgumentOutOfRangeException:子节点索引超出范围">子节点索引超出范围</exception>
    128         public NTree<T> GetChild(int i)
    129         {
    130             if (i >= children.Count || i < 0)
    131             {
    132                 throw new ArgumentOutOfRangeException("子节点索引超出范围");
    133             }
    134             return children[i];
    135         }
    136         /// <summary>
    137         /// 获取指定的子节点
    138         /// </summary>
    139         /// <param name="data">节点数据</param>
    140         /// <returns>查找到的第一个子节点</returns>
    141         public NTree<T> GetChild(T data)
    142         {
    143             return children.Where(i => i.data.Equals(data)).FirstOrDefault();
    144         }
    145         /// <summary>
    146         /// 获取指定子节点的索引
    147         /// </summary>
    148         /// <param name="data">节点数据</param>
    149         /// <returns>查找到的第一个子节点的索引,没有找到返回-1</returns>
    150         public int GetChildIndex(NTree<T> data)
    151         {
    152             var index = -1;
    153             for (int i = 0; i < children.Count; i++)
    154             {
    155                 if (children[i].Equals(data))
    156                 {
    157                     index = i;
    158                     break;
    159                 }
    160             }
    161             return index;
    162         }
    163         /// <summary>
    164         /// 遍历树节点
    165         /// </summary>
    166         /// <param name="node">起始节点</param>
    167         /// <param name="action">遍历到每个节点的操作</param>
    168         /// <exception cref="ArgumentNullException:参数action不可为空">参数action不可为空</exception>
    169         public static void Traverse(NTree<T> node, Action<T> action)
    170         {
    171             if (action == null)
    172             {
    173                 throw new ArgumentNullException("参数action不可为空");
    174             }
    175             action(node.data);
    176             foreach (var kid in node.children)
    177             {
    178                 Traverse(kid, action);
    179             }
    180         }
    181         /// <summary>
    182         /// 从当前节点开始遍历树节点
    183         /// </summary>
    184         /// <param name="action">遍历到每个节点的操作</param>
    185         /// <exception cref="ArgumentNullException:参数action不可为空">参数action不可为空</exception>
    186         public void Traverse(Action<T> action)
    187         {
    188             Traverse(this, action);
    189         }
    190         /// <summary>
    191         /// 遍历树节点
    192         /// </summary>
    193         /// <param name="node">起始节点</param>
    194         /// <param name="action">遍历到每个节点的操作</param>
    195         /// <exception cref="ArgumentNullException:参数action不可为空">参数action不可为空</exception>
    196         public static void Traverse(NTree<T> node, Action<NTree<T>> action)
    197         {
    198             if (action == null)
    199             {
    200                 throw new ArgumentNullException("参数action不可为空");
    201             }
    202             action(node);
    203             foreach (var kid in node.children)
    204             {
    205                 Traverse(kid, action);
    206             }
    207         }
    208         /// <summary>
    209         /// 从当前节点开始遍历树节点
    210         /// </summary>
    211         /// <param name="action">遍历到每个节点的操作</param>
    212         /// <exception cref="ArgumentNullException:参数action不可为空">参数action不可为空</exception>
    213         public void Traverse(Action<NTree<T>> action)
    214         {
    215             if (action == null)
    216             {
    217                 throw new ArgumentNullException("参数action不可为空");
    218             }
    219             action(this);
    220             foreach (var kid in this.children)
    221             {
    222                 Traverse(kid, action);
    223             }
    224         }
    225         /// <summary>
    226         /// 获取当前节点开始的所有节点中数据
    227         /// </summary>
    228         /// <returns>节点数据列表</returns>
    229         public IEnumerable<T> GetDatas()
    230         {
    231             return new[] { data }.Union(children.SelectMany(x => x.GetDatas()));
    232         }
    233         /// <summary>
    234         /// 当前节点下叶节点的数量
    235         /// </summary>
    236         /// <returns></returns>
    237         public int GetCount()
    238         {
    239             var count = 0;
    240             Traverse((NTree<T> n) =>
    241             {
    242                 if (n.Children.Count == 0)
    243                 {
    244                     count++;
    245                 }
    246             });
    247             return count;
    248         }
    249         /// <summary>
    250         /// 获取当前节点所在树的深度
    251         /// </summary>
    252         /// <returns>当前节点所在树的深度</returns>
    253         public int GetTreeDepth()
    254         {
    255             int Depth = 1;
    256             var parent = this;
    257             while (parent.Parent != null)
    258             {
    259                 parent = parent.Parent;
    260             }
    261             Traverse((NTree<T> n) =>
    262             {
    263                 if (Depth < n.Depth)
    264                 {
    265                     Depth = n.Depth;
    266                 }
    267             });
    268 
    269             return Depth;
    270         }
    271     }
    272     /// <summary>
    273     /// 父节点为空引用异常
    274     /// </summary>
    275     public class NullParentNodeException : Exception
    276     {
    277         public NullParentNodeException()
    278             : base("父节点为空引用")
    279         {
    280 
    281         }
    282         public NullParentNodeException(string message)
    283             : base(message)
    284         {
    285 
    286         }
    287         public NullParentNodeException(string message, Exception inner)
    288             : base(message)
    289         {
    290 
    291         }
    292         //public NullParentNodeException(SerializationInfo info, StreamingContext context)
    293         //{
    294 
    295         //}
    296     }
    297 }
    View Code

    MultiHeadersColumn:多重表头和绑定的列

    IDataGridHeader:定义生成表头和绑定列的数据接口

      1 using System;
      2 using System.Windows;
      3 using System.Windows.Controls;
      4 using System.Collections.Generic;
      5 using System.Windows.Markup;
      6 using System.Text;
      7 
      8 namespace SLDGHeader
      9 {
     10     public class MultiHeadersColumn
     11     {
     12         #region 字段
     13         /// <summary>
     14         /// 单元格边框颜色
     15         /// </summary>
     16         string splitLineColor = "#ccc";
     17         /// <summary>
     18         /// 数据行宽度
     19         /// </summary>
     20         string dataWidth = "30";
     21         /// <summary>
     22         /// 表头行高度
     23         /// </summary>
     24         string dataHeight = "auto";
     25         /// <summary>
     26         /// 分隔线线宽度
     27         /// </summary>
     28         string lineWidth = "1";
     29         /// <summary>
     30         /// 分隔符线高度
     31         /// </summary>
     32         string lineHeight = "1";
     33         #endregion
     34         #region 属性
     35         /// <summary>
     36         /// 单元格边框颜色
     37         /// </summary>
     38         public string SplitLineColor
     39         {
     40             get { return splitLineColor; }
     41             set { splitLineColor = value; }
     42         }
     43         /// <summary>
     44         /// 数据行宽度
     45         /// </summary>
     46         public string DataWidth
     47         {
     48             get { return dataWidth; }
     49             set { dataWidth = value; }
     50         }
     51         /// <summary>
     52         /// 表头行高度
     53         /// </summary>
     54         public string DataHeight
     55         {
     56             get { return dataHeight; }
     57             set { dataHeight = value; }
     58         }
     59         /// <summary>
     60         /// 分隔线线宽度
     61         /// </summary>
     62         public string LineWidth
     63         {
     64             get { return lineWidth; }
     65             set { lineWidth = value; }
     66         }
     67         /// <summary>
     68         /// 分隔符线高度
     69         /// </summary>
     70         public string LineHeight
     71         {
     72             get { return lineHeight; }
     73             set { lineHeight = value; }
     74         }
     75         #endregion
     76         public DataGridTemplateColumn GetMultiHeadersColumn(NTree<IDataGridHeader> node)
     77         {
     78             DataGridTemplateColumn col = GetTemplateColumn(node);
     79             col.HeaderStyle = GetStyle("NameHeaderStyle", node);
     80             return col;
     81         }
     82         DataGridTemplateColumn GetTemplateColumn(NTree<IDataGridHeader> node)
     83         {
     84             List<NTree<IDataGridHeader>> nodes = new List<NTree<IDataGridHeader>>();
     85             node.Traverse((NTree<IDataGridHeader> n) =>
     86             {
     87                 if (n.Children.Count == 0)
     88                 {
     89                     nodes.Add(n);
     90                 }
     91             });
     92             string strtemplate = GetDataTemplate(nodes);
     93             DataTemplate template = (DataTemplate)XamlReader.Load(strtemplate);
     94 
     95             DataGridTemplateColumn colunm = new DataGridTemplateColumn();
     96             colunm.CellTemplate = template;
     97 
     98             return colunm;
     99         }
    100         /// <summary>
    101         /// 获取绑定列模板XML字符串
    102         /// </summary>
    103         /// <param name="nodes">列对应节点</param>
    104         /// <returns>返回列模板XML字符串</returns>
    105         string GetDataTemplate(List<NTree<IDataGridHeader>> nodes)
    106         {
    107             if (nodes == null)
    108             {
    109                 throw new ArgumentNullException("参数nodes不能为空");
    110             }
    111             StringBuilder sb = new StringBuilder(200);
    112 
    113             sb.Append(@"<DataTemplate ");
    114             sb.AppendLine("xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' ");
    115             sb.AppendLine("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' ");
    116             sb.AppendLine("xmlns:sdk='http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk'");
    117             sb.AppendLine(" >");
    118 
    119             sb.AppendLine("<StackPanel Orientation='Horizontal'> ");
    120             for (int i = 0; i < nodes.Count * 2 - 1; i++)
    121             {
    122                 if (i % 2 == 0)
    123                 {
    124                     sb.Append("<TextBlock VerticalAlignment='Center' ");
    125                     sb.Append(" Width='").Append(dataWidth).Append("' ");
    126                     sb.Append(" HorizontalAlignment='Center' TextWrapping='Wrap' Text='{Binding ").Append(nodes[(i + 1) / 2].Data.ColName).AppendLine("}' /> ");
    127                 }
    128                 else
    129                 {
    130                     sb.Append(" <Rectangle Fill='").Append(splitLineColor).Append("' VerticalAlignment='Stretch' ");
    131                     sb.Append(" Width='").Append(lineWidth).Append("' ");
    132                     sb.AppendLine(" /> ");
    133                 }
    134             }
    135 
    136             sb.AppendLine("</StackPanel> ");
    137             sb.AppendLine("</DataTemplate> ");
    138             return sb.ToString();
    139         }
    140 
    141         Style GetStyle(string headerstyle, NTree<IDataGridHeader> node)
    142         {
    143             var depth = node.GetTreeDepth();
    144             string stylestr = GetStyleStr("NameHeaderStyle", depth, node);
    145             Style ste = (Style)XamlReader.Load(stylestr);
    146 
    147             return ste;
    148         }
    149         /// <summary>
    150         /// 获取表头样式XML字符串
    151         /// </summary>
    152         /// <param name="headerstyle">样式名称</param>
    153         /// <param name="depth">树的深度</param>
    154         /// <param name="node">树的根节点</param>
    155         /// <returns>返回表头样式XML字符串</returns>
    156         string GetStyleStr(string headerstyle, int depth, NTree<IDataGridHeader> node)
    157         {
    158 
    159             StringBuilder sb = new StringBuilder(2000);
    160             //计算数据列数量
    161             int colCount = node.GetCount();
    162 
    163             AppendHeader(headerstyle, sb);
    164             //构建表头行列
    165             sb.AppendLine("<Grid HorizontalAlignment='{TemplateBinding HorizontalContentAlignment}' VerticalAlignment='{TemplateBinding VerticalContentAlignment}'>");
    166             //多少行
    167             sb.AppendLine("<Grid.RowDefinitions>");
    168             //int rowCount = 3;
    169             for (int i = 0; i < depth * 2; i++)
    170             {
    171                 if (i % 2 == 0)
    172                 {
    173                     sb.AppendLine("<RowDefinition ");
    174                     sb.Append(" Height='").Append(dataHeight).Append("' ");
    175                     sb.AppendLine(" /> ");
    176                 }
    177                 else
    178                 {
    179                     sb.AppendLine("<RowDefinition ");
    180                     sb.Append(" Height='").Append(lineHeight).Append("' ");
    181                     sb.AppendLine("/>");
    182                 }
    183             }
    184             sb.AppendLine("</Grid.RowDefinitions>");
    185 
    186             //多少列
    187             sb.AppendLine("<Grid.ColumnDefinitions>");
    188 
    189             for (int i = 0; i < colCount * 2; i++)
    190             {
    191                 if (i % 2 == 0)
    192                 {
    193                     sb.AppendLine("<ColumnDefinition ");
    194                     sb.Append("Width='").Append(dataWidth).Append("' ");
    195                     sb.AppendLine(" />");
    196                 }
    197                 else
    198                 {
    199                     sb.AppendLine("<ColumnDefinition ");
    200                     sb.Append("Width='").Append(lineWidth).Append("' ");
    201                     sb.AppendLine(" />");
    202                 }
    203 
    204             }
    205             sb.AppendLine("</Grid.ColumnDefinitions>");
    206 
    207             //开始构单元格
    208             AppendCell(node, sb, depth, colCount);
    209 
    210 
    211             AppendEnd(sb);
    212 
    213             return sb.ToString();
    214         }
    215         /// <summary>
    216         /// 绘制头部和表头背景
    217         /// </summary>
    218         /// <param name="headerstyle">样式名称</param>
    219         /// <param name="sb"></param>
    220         private void AppendHeader(string headerstyle, StringBuilder sb)
    221         {
    222             sb.Append(@"<Style ");
    223             sb.AppendLine("xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' ");
    224             sb.AppendLine("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' ");
    225             sb.AppendLine("xmlns:dataprimitives='clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Data' ");
    226 
    227             //列样式名称
    228             sb.Append(@" x:Key='").Append(headerstyle).Append("' ");
    229 
    230             sb.AppendLine(@"TargetType='dataprimitives:DataGridColumnHeader' >");
    231             sb.AppendLine("<Setter Property='Template'>");
    232             sb.AppendLine("<Setter.Value>");
    233             sb.AppendLine("<ControlTemplate>");
    234             sb.AppendLine("<Grid x:Name='Root'>");
    235             sb.AppendLine("<Grid.ColumnDefinitions>");
    236             sb.AppendLine("<ColumnDefinition/>");
    237             sb.AppendLine("<ColumnDefinition Width='Auto'/>");
    238             sb.AppendLine("</Grid.ColumnDefinitions>");
    239             sb.AppendLine("<Rectangle x:Name='BackgroundRectangle' Fill='#FF1F3B53' Stretch='Fill' Grid.ColumnSpan='2'/>");
    240             sb.AppendLine("<Rectangle x:Name='BackgroundGradient' Stretch='Fill' Grid.ColumnSpan='2'>");
    241             sb.AppendLine("<Rectangle.Fill>");
    242             //表头背景色
    243             sb.AppendLine("<LinearGradientBrush EndPoint='.7,1' StartPoint='.7,0'>");
    244             sb.AppendLine(@"<GradientStop Color='#FCFFFFFF' Offset='0.015'/>
    245                         <GradientStop Color='#F7FFFFFF' Offset='0.375'/>
    246                         <GradientStop Color='#E5FFFFFF' Offset='0.6'/>
    247                         <GradientStop Color='#D1FFFFFF' Offset='1'/>");
    248             sb.AppendLine("</LinearGradientBrush>");
    249             sb.AppendLine("</Rectangle.Fill>");
    250             sb.AppendLine("</Rectangle>");
    251         }
    252         /// <summary>
    253         /// 添加结束XML部分
    254         /// </summary>
    255         /// <param name="sb"></param>
    256         private void AppendEnd(StringBuilder sb)
    257         {
    258             sb.AppendLine("</Grid>");
    259             //绘制最后一列分割线
    260             sb.AppendLine(@"<Rectangle x:Name='VerticalSeparator' Fill='")
    261                 .Append(splitLineColor)
    262                 .Append(@"' VerticalAlignment='Stretch'")
    263                 .Append(" Width='").Append(lineWidth).Append("' ")
    264                 .AppendLine(" Visibility='Visible' Grid.Row='1' Grid.Column='1' />");
    265             sb.AppendLine("</Grid>");
    266             sb.AppendLine("</ControlTemplate>");
    267             sb.AppendLine("</Setter.Value>");
    268             sb.AppendLine("</Setter>");
    269             sb.AppendLine("</Style>");
    270         }
    271         /// <summary>
    272         /// 构建行
    273         /// 偶数行、偶数列为数据,奇数行、奇数列为分割线,以此计算单元格占位、合并行列
    274         /// </summary>
    275         /// <param name="node">构建行的树结构</param>
    276         /// <param name="sb">字符串</param>
    277         /// <param name="depth">树的深度</param>
    278         private StringBuilder AppendCell(NTree<IDataGridHeader> node, StringBuilder sb, int depth, int totalCol)
    279         {
    280             //当前节点左兄弟节点的页节点数量,用于计算当前单元格列位置
    281             var precolCount = 0;
    282             if (!node.IsRoot)
    283             {
    284                 precolCount = GetLeftCount(node);
    285             }
    286 
    287             //当前节点的页节点数量
    288             var colCount = node.GetCount();
    289 
    290             //1、数据单元格
    291             sb.Append(@"<ContentPresenter  ");
    292             sb.Append(@"Content='").Append(node.Data.DisplayColName).Append("' ");
    293             sb.Append(@"VerticalAlignment='Center' HorizontalAlignment='Center' ");
    294             sb.Append(" Grid.Row='").Append((node.Depth - 1) * 2).Append("' ");
    295             //考虑表头行可能不一致(层级有深有浅),层级较少的需要合并列显示,所有合并在最后一行表头
    296             var rowSpan = 1;
    297             if (node.Children.Count == 0 && node.Depth != depth)
    298             {
    299                 rowSpan = depth * 2 - 1 - (node.Depth - 1) * 2;
    300                 sb.Append(" Grid.RowSpan='").Append(rowSpan).Append("' ");
    301             }
    302 
    303             sb.Append(" Grid.Column='").Append(precolCount * 2).Append("' ");
    304             sb.Append("Grid.ColumnSpan='").Append(colCount * 2 - 1).AppendLine("' />");
    305 
    306             //2、行分隔线单元格
    307             sb.Append(@"<Rectangle Fill='").Append(splitLineColor).Append("' VerticalAlignment='Stretch' ")
    308                 .Append("Height='").Append(lineHeight).Append("' ");
    309 
    310             //表头行合并后要调整分割线,否则会在合并单元格中间显示分割线
    311             if (node.Children.Count == 0 && node.Depth != depth)
    312             {
    313                 //如果有合并单元,则分割线要跳过合并单元格,合并数量为(rowSpan - 1)
    314                 sb.Append("Grid.Row='").Append(node.Depth * 2 - 1 + rowSpan - 1).Append("' ");
    315             }
    316             else
    317             {
    318                 sb.Append("Grid.Row='").Append(node.Depth * 2 - 1).Append("' ");
    319             }
    320 
    321             sb.Append(" Grid.Column='").Append(precolCount * 2).Append("' ");
    322             sb.Append("Grid.ColumnSpan='").Append(colCount * 2).AppendLine("' />");
    323 
    324             //4、列分隔线单元格
    325             //最后一列分割线不绘制,否则在调整了后面列的列宽会出现类似空列的单元格
    326             if ((precolCount + colCount) != totalCol)
    327             {
    328                 sb.Append(@"<Rectangle Fill='").Append(splitLineColor).Append("' VerticalAlignment='Stretch' ")
    329                     .Append(" Width='").Append(lineWidth).Append("' ");
    330 
    331                 sb.Append("Grid.Row='").Append((node.Depth - 1) * 2).Append("' ");
    332                 sb.Append("Grid.RowSpan='").Append(rowSpan).Append("' ");
    333                 sb.Append("Grid.Column='").Append((precolCount + colCount) * 2 - 1).AppendLine("' />");
    334             }
    335 
    336 
    337             //5、递归生成子节点单元格
    338             if (node.Children.Count != 0)
    339             {
    340                 foreach (var item1 in node.Children)
    341                 {
    342                     AppendCell(item1, sb, depth, totalCol);
    343                 }
    344             }
    345 
    346 
    347             return sb;
    348         }
    349         /// <summary>
    350         /// 获取当前节点左边的叶节点数量
    351         /// </summary>
    352         /// <param name="node"></param>
    353         /// <returns></returns>
    354         private int GetLeftCount(NTree<IDataGridHeader> node)
    355         {
    356             var precolCount = 0;
    357             var index = node.Parent.GetChildIndex(node);
    358             for (int i = 0; i < index; i++)
    359             {
    360                 precolCount += node.Parent.GetChild(i).GetCount();
    361             }
    362             if (!node.Parent.IsRoot)
    363             {
    364                 precolCount += GetLeftCount(node.Parent);
    365             }
    366             return precolCount;
    367         }
    368     }
    369     public interface IDataGridHeader
    370     {
    371         /// <summary>
    372         /// 绑定列名
    373         /// </summary>
    374         string ColName { get; set; }
    375         /// <summary>
    376         /// 显示名称
    377         /// </summary>
    378         string DisplayColName { get; set; }
    379     }
    380 }
    View Code
  • 相关阅读:
    C# json转对象
    sit、qas、dev、pet
    vs professional 2019 离线安装包下载方法
    C# SHA512和Base64加解密方法
    C#获取客户端Ip工具类
    C#xml泛型序列化
    C#对象转换工具类
    C#记录日志到本地文件工具类
    05 Activity生命周期
    05 利用Appliction 传值Activity
  • 原文地址:https://www.cnblogs.com/missile/p/7133503.html
Copyright © 2020-2023  润新知