翼度科技»论坛 编程开发 .net 查看内容

使用扩展函数方式,在Winform界面中快捷的绑定树形列表TreeList控件和TreeL

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
在一些字典绑定中,往往为了方便展示详细数据,需要把一些结构树展现在树列表TreeList控件中或者下拉列表的树形控件TreeListLookUpEdit控件中,为了快速的处理数据的绑定操作,比较每次使用涉及太多细节的操作,我们可以把相关的数据绑定操作,放在一些辅助类的扩展函数中进行处理,这样可以更方便的,更简洁的处理数据绑定操作,本篇随笔介绍TreeList控件和TreeListLookUpEdit控件在扩展函数中的处理操作。
1、TreeList控件的绑定操作

TreeList本身就是一个树形数据的展示控件,可以展示常规的二维表,也可以展示具有嵌套关系的二维表,数据源可以是多种方式的,支持Datable的数据源的嵌套展示。
单个列信息的树形列表展示界面效果:

 类似GridView的嵌套列表展示的TreeList界面效果

 这些界面都比较常见,也是我们经常碰到的处理效果,但是TreeList的界面设置有很多特性,如果每次拷贝这些代码,需要很多,也不便于维护,因此我们建立一些扩展函数来处理界面元素的绑定,就非常必要。

本篇随笔介绍基于TreeList和TreeListLookUpEdit控件的绑定即可。两个类型控件的数据源,都可以是DataTable类型,也可以是IList集合类型,如下所示是基于SQLSugar开发框架,返回的数据结构是IList类型的。

所以一般树形列表的绑定操作,提供一个方法来获取数据并绑定即可。
  1.         /// <summary>
  2.         /// 绑定树的数据源
  3.         /// </summary>
  4.         private async void BindTree()
  5.         {
  6.             var list = await BLLFactory<IDictTypeService>.Instance.GetAllAsync();
  7.             this.tree.DataSource = list?.Items;
  8.             this.tree.ExpandAll();
  9.         }
复制代码
如果使用原生代码初始化树列表,那么代码如下所示。
  1. //使用原生代码处理
  2. //添加显示列
  3. this.tree.Columns.Add(new TreeListColumn{ FieldName= "Id", Caption= "ID"});//增加一个隐藏的字段,存储需要的ID
  4. this.tree.Columns.Add(new TreeListColumn{ FieldName= "Name", Caption= "字典类型名称", Width=160, VisibleIndex =0});
  5. //设置树控件的层次关系及属性
  6. tree.KeyFieldName = "Id";
  7. tree.ParentFieldName = "PID";
  8. this.tree.OptionsBehavior.Editable = false;
  9. this.tree.OptionsView.ShowColumns = false;
  10. this.tree.OptionsView.ShowCheckBoxes = false;
  11. this.tree.OptionsView.EnableAppearanceOddRow = true;
  12. this.tree.OptionsView.EnableAppearanceEvenRow = true;
复制代码
而实现查询过滤的操作,还需要另外处理代码,我们看看大概的代码如下。
  1.         /// <summary>
  2.         /// 实现树节点的过滤查询
  3.         /// </summary>
  4.         private void InitSearchControl()
  5.         {
  6.             this.searchControl1.Client = this.tree;
  7.             this.tree.FilterNode += (object sender, FilterNodeEventArgs e) =>
  8.             {
  9.                 if (tree.DataSource == null)
  10.                     return;
  11.                 string nodeText = e.Node.GetDisplayText("Name");//参数填写FieldName  
  12.                 if (string.IsNullOrWhiteSpace(nodeText))
  13.                     return;
  14.                 bool isExist = nodeText.IndexOf(searchControl1.Text, StringComparison.OrdinalIgnoreCase) >= 0;
  15.                 if (isExist)
  16.                 {
  17.                     var node = e.Node.ParentNode;
  18.                     while (node != null)
  19.                     {
  20.                         if (!node.Visible)
  21.                         {
  22.                             node.Visible = true;
  23.                             node = node.ParentNode;
  24.                         }
  25.                         else
  26.                             break;
  27.                     }
  28.                 }
  29.                 e.Node.Visible = isExist;
  30.                 e.Handled = true;
  31.             };
  32.         }
复制代码
这些是比较常见的操作,我们把它封装为扩展函数,然后根据特性传入对应参数实现即可。
最后简单的三行代码来简单处理,可以达到同样的效果就可以了。
  1.   //控件扩展函数封装处理
  2.   this.tree.CreateColumn("Name", "字典类型名称", 160, true);
  3.   this.tree.InitTree("Id", "PID", "-1", false, false);
  4.   this.tree.InitSearchControl(this.searchControl1, "Name");
复制代码
我们扩展方法放在一个单独的文件中,标注为静态类即可。
  1.     /// <summary>
  2.     /// TreeList控件的扩展函数
  3.     /// </summary>
  4.     public static class TreeList_Extension
复制代码
其中提供几个对TreeList 常见的封装处理方法就可以了。

对于一些不常见的属性,我们保留它即可,如下界面代码是对TreeList绑定展示多个列的处理操作。
  1. /// <summary>
  2. /// 初始化TreeList控件,展现嵌套的列表。
  3. /// </summary>
  4. private void InitControl()
  5. {
  6.     this.tree.Columns.Clear();//控件扩展函数封装处理
  7.     this.tree.CreateColumn("Name", "机构名称", 160, true);
  8.     this.tree.CreateColumn("HandNo", "机构编码", 80, true);
  9.     this.tree.CreateColumn("Category", "机构分类", 80, true);
  10.     this.tree.CreateColumn("Address", "机构地址", 160, true);
  11.     this.tree.CreateColumn("InnerPhone", "内线电话", 80, true);
  12.     this.tree.CreateColumn("OuterPhone", "外线电话", 80, true);
  13.     this.tree.CreateColumn("SortCode", "排序码", 80, true);
  14.     <strong>this.tree.InitTree("Id", "PID", null, true, true);
  15.     </strong>this.tree.OptionsView.RowImagesShowMode = RowImagesShowMode.InCell;//紧凑型图标
  16.     this.tree.ExpandAll();
  17.     // 列过滤处理            
  18.     this.tree.OptionsView.ShowAutoFilterRow = true;//显示过滤行            
  19.     this.tree.OptionsBehavior.EnableFiltering = true;//开启过滤功能
  20.     //初始化树节点选择事件
  21.     this.tree.FocusedNodeChanged += delegate (object sender, FocusedNodeChangedEventArgs e)
  22.     {
  23.         this.FocusedNodeChanged();
  24.     };
  25.     //树节点双击处理事件
  26.     this.tree.DoubleClick += (s, e) =>
  27.     {
  28.         if (this.tree.FocusedNode != null)
  29.         {
  30.             string ID = string.Concat(this.tree.FocusedNode.GetValue("Id"));
  31.             MessageDxUtil.ShowTips("Id=" + ID);
  32.         }
  33.     };
  34.     //编辑记录失去焦点后校验处理
  35.     this.tree.ValidateNode += (s, e) =>
  36.     {
  37.         Console.WriteLine(this.tree.FocusedNode.GetValue("Name"));
  38.     };
  39. }
复制代码
实现类似GridView的嵌套列表展示的TreeList界面效果如下所示。

 
2、TreeListLookUpEdit控件绑定操作

在一些参考的列表中,我们往往需要展示更丰富一点的列表内容,如下所示。


如果有嵌套列表的,展示嵌套列表的处理

对于下拉的树形列表,虽然这个控件比TreeList更复杂一些,它是下拉列表和TreeList的整合体,不过我们也可以用类似的扩展函数方法,来简单的实现数据的绑定展示。
如对于常规的数据绑定,我们大概的代码如下所示。
  1. //TreeListLookupEdit数据绑定
  2. //this.txtProjectList3.Properties.TreeList.OptionsView.ShowCheckBoxes = true;
  3. this.txtProjectList3.Properties.DataSource = list;
  4. this.txtProjectList3.Properties.ValueMember = "Value";
  5. this.txtProjectList3.Properties.DisplayMember = "Text";
  6. this.txtProjectList3.Properties.TreeList.Columns.Clear();
  7. for (int i = 0; i < columns.Count; i++)
  8. {
  9.     this.txtProjectList3.Properties.TreeList.CreateColumn(columns[i].FieldName, columns[i].Caption,
  10.         columns[i].Width, true);
  11. }
  12. this.txtProjectList3.Properties.TreeList.InitTree(null, null, null, true, true);
  13. this.txtProjectList3.Properties.ImmediatePopup = true;
  14. this.txtProjectList3.Properties.TextEditStyle = TextEditStyles.Standard;
  15. this.txtProjectList3.Properties.PopupWidthMode = DevExpress.XtraEditors.PopupWidthMode.ContentWidth;
  16. this.txtProjectList3.Properties.PopupFormSize = new System.Drawing.Size(this.txtProjectList3.Width, 300);
  17. this.txtProjectList3.Properties.TreeList.IndicatorWidth = 40;
  18. this.txtProjectList3.Properties.TreeList.CustomDrawNodeIndicator += (s, ee) =>
  19. {
  20.     if (ee.IsNodeIndicator)
  21.     {
  22.         var index = ee.Node.TreeList.GetVisibleIndexByNode(ee.Node);
  23.         ee.Info.DisplayText = (index + 1).ToString();
  24.     }
  25. };
复制代码
对于常规的列表绑定,我们可以用简单的一个扩展函数实现,如下所示。
  1.     //常规类别绑定
  2.     this.txtProjectList4.BindDictItems(list, "Text", "Value", true, columns.ToArray());
复制代码
就可以实现常规的界面效果处理。

对于树形列表,我们需要设置属性的ID和PID,以及一些显示的列属性,那么也可以增加更多的参数来实现。
  1. var dictTypeColumns = new List<LookUpColumnInfo>()
  2. {
  3.     new LookUpColumnInfo("Id", "Id"),
  4.     new LookUpColumnInfo("Name", "字典类别名称")
  5. };
  6. treeListLookUp.BindDictItems(result.Items, "Name", "Id", true, false, "Id", "PID", null, true, true, true, false, dictTypeColumns.ToArray());
复制代码
因此嵌套列表就可以正常的展示出层次关系了

因此我们把扩展方法,放到静态类里面就可以了,方法封装如下所示
  1.        /// <summary>
  2.         /// 绑定TreeListLookUpEdit控件的数据源(完整版)
  3.         /// </summary>
  4.         /// <param name="lookup">控件对象</param>
  5.         /// <param name="dataSource">数据源</param>
  6.         /// <param name="displayMember">显示字段</param>
  7.         /// <param name="valueMember">值字段</param>
  8.         /// <param name="showRowIndicator">是否显示序号</param>
  9.         /// <param name="showCheckbox">是否显示复选框</param>
  10.         /// <param name="keyFieldName">设置父子递归关系字段-子字段,不指定则使用valueMember</param>
  11.         /// <param name="parentFieldName">设置父子递归关系字段-父字段,不指定则不嵌套展示</param>
  12.         /// <param name="rootValue">根节点的值</param>
  13.         /// <param name="editable">树节点是否可以编辑</param>
  14.         /// <param name="showColumnHeader">是否显示列头</param>
  15.         /// <param name="oddEvenRowColor">是否奇偶行不同颜色</param>
  16.         /// <param name="allowDrop">是否运行拖动列</param>
  17.         /// <param name="lookUpColumnInfos">显示的列</param>
  18.         /// <returns></returns>
  19.         public static object BindDictItems(this TreeListLookUpEdit lookup, object dataSource, string displayMember, string valueMember, bool showRowIndicator = true,
  20.             bool showCheckbox = false, string keyFieldName = null, string parentFieldName = null, string rootValue = null, bool editable = true,
  21.             bool showColumnHeader = false, bool oddEvenRowColor = true, bool allowDrop = false,
  22.             params LookUpColumnInfo[] lookUpColumnInfos)
  23.         {
  24.             lookup.Properties.DataSource = dataSource;
  25.             lookup.Properties.DisplayMember = displayMember;
  26.             lookup.Properties.ValueMember = valueMember;
  27.             lookup.Properties.TreeList.OptionsView.ShowCheckBoxes = showCheckbox;
  28.             lookup.Properties.TreeList.Columns.Clear();
  29.             for (int i = 0; i < lookUpColumnInfos.Length; i++)
  30.             {
  31.                 lookup.Properties.TreeList.CreateColumn(lookUpColumnInfos[i].FieldName, lookUpColumnInfos[i].Caption,
  32.                     lookUpColumnInfos[i].Width, true);
  33.             }
  34.             //初始化树的样式和特性
  35.             //keyFieldName = !string.IsNullOrWhiteSpace(keyFieldName) ? keyFieldName : valueMember;//如果不指定,采用valueMember
  36.             lookup.Properties.TreeList.InitTree(keyFieldName, parentFieldName, rootValue, editable, showColumnHeader, oddEvenRowColor, allowDrop);
  37.             lookup.Properties.PopupFormSize = new System.Drawing.Size(lookup.Width, 300);
  38.             lookup.Properties.ImmediatePopup = true;
  39.             lookup.Properties.TextEditStyle = TextEditStyles.Standard;
  40.             if (showRowIndicator)
  41.             {
  42.                 lookup.Properties.TreeList.IndicatorWidth = 40;
  43.                 //重写序号显示,默认不显示数值
  44.                 lookup.Properties.TreeList.CustomDrawNodeIndicator += (s, ee) =>
  45.                 {
  46.                     if (ee.IsNodeIndicator)
  47.                     {
  48.                         var index = ee.Node.TreeList.GetVisibleIndexByNode(ee.Node);
  49.                         ee.Info.DisplayText = (index + 1).ToString();
  50.                     }
  51.                 };
  52.             }
  53.             return dataSource;
  54.         }
复制代码
通过扩展方法的方式,可以简化界面的处理代码,同时利于我们在项目开发的时候,快速的实现相关的效果,而不需要过多的中断查找相关的界面控件属性。
有几篇类似的文章,可供参考:
在Winform开发中,我们使用的几种下拉列表展示字典数据的方式
在Winform开发框架中下拉列表绑定字典以及使用缓存提高界面显示速度
在各种开发项目中使用公用类库的扩展方法,通过上下文方式快速调用处理函数
 

来源:https://www.cnblogs.com/wuhuacong/archive/2023/04/25/17353173.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具