Silverlight多重表头实现

Posted 小神仙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 { Silverlight 中的十进制转换器无法正确处理丢失焦点

优化 C# 代码片段、ObservableCollection 和 AddRange

ArcGIS API for Silverlight动态标绘的实现

XAML silverlight 中的填充图案

DataGrid和Silverlight

HTML或JS代码如何实现让一个table的表头不动,body可以自由上下左右滚动,同时保持表头与body的宽度一致?