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

1、TreeList控件的绑定操作

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

单个列信息的树形列表展示界面效果:

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

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

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

所以一般树形列表的绑定操作,提供一个方法来获取数据并绑定即可。

        /// <summary>
/// 绑定树的数据源
/// </summary>
private async void BindTree()
{
var list = await BLLFactory<IDictTypeService>.Instance.GetAllAsync();
this.tree.DataSource = list?.Items;
this.tree.ExpandAll();
}

如果使用原生代码初始化树列表,那么代码如下所示。

 //使用原生代码处理
//添加显示列
this.tree.Columns.Add(new TreeListColumn{ FieldName= "Id", Caption= "ID"});//增加一个隐藏的字段,存储需要的ID
this.tree.Columns.Add(new TreeListColumn{ FieldName= "Name", Caption= "字典类型名称", Width=160, VisibleIndex =0});
//设置树控件的层次关系及属性
tree.KeyFieldName = "Id";
tree.ParentFieldName = "PID";
this.tree.OptionsBehavior.Editable = false;
this.tree.OptionsView.ShowColumns = false;
this.tree.OptionsView.ShowCheckBoxes = false;
this.tree.OptionsView.EnableAppearanceOddRow = true;
this.tree.OptionsView.EnableAppearanceEvenRow = true;

而实现查询过滤的操作,还需要另外处理代码,我们看看大概的代码如下。

        /// <summary>
/// 实现树节点的过滤查询
/// </summary>
private void InitSearchControl()
{
this.searchControl1.Client = this.tree;
this.tree.FilterNode += (object sender, FilterNodeEventArgs e) =>
{
if (tree.DataSource == null)
return; string nodeText = e.Node.GetDisplayText("Name");//参数填写FieldName
if (string.IsNullOrWhiteSpace(nodeText))
return; bool isExist = nodeText.IndexOf(searchControl1.Text, StringComparison.OrdinalIgnoreCase) >= 0;
if (isExist)
{
var node = e.Node.ParentNode;
while (node != null)
{
if (!node.Visible)
{
node.Visible = true;
node = node.ParentNode;
}
else
break;
}
}
e.Node.Visible = isExist;
e.Handled = true;
};
}

这些是比较常见的操作,我们把它封装为扩展函数,然后根据特性传入对应参数实现即可。

最后简单的三行代码来简单处理,可以达到同样的效果就可以了。

  //控件扩展函数封装处理
this.tree.CreateColumn("Name", "字典类型名称", 160, true);
this.tree.InitTree("Id", "PID", "-1", false, false);
this.tree.InitSearchControl(this.searchControl1, "Name");

我们扩展方法放在一个单独的文件中,标注为静态类即可。

    /// <summary>
/// TreeList控件的扩展函数
/// </summary>
public static class TreeList_Extension

其中提供几个对TreeList 常见的封装处理方法就可以了。

对于一些不常见的属性,我们保留它即可,如下界面代码是对TreeList绑定展示多个列的处理操作。

/// <summary>
/// 初始化TreeList控件,展现嵌套的列表。
/// </summary>
private void InitControl()
{
this.tree.Columns.Clear();//控件扩展函数封装处理
this.tree.CreateColumn("Name", "机构名称", 160, true);
this.tree.CreateColumn("HandNo", "机构编码", 80, true);
this.tree.CreateColumn("Category", "机构分类", 80, true);
this.tree.CreateColumn("Address", "机构地址", 160, true);
this.tree.CreateColumn("InnerPhone", "内线电话", 80, true);
this.tree.CreateColumn("OuterPhone", "外线电话", 80, true);
this.tree.CreateColumn("SortCode", "排序码", 80, true);
this.tree.InitTree("Id", "PID", null, true, true); this.tree.OptionsView.RowImagesShowMode = RowImagesShowMode.InCell;//紧凑型图标
this.tree.ExpandAll(); // 列过滤处理
this.tree.OptionsView.ShowAutoFilterRow = true;//显示过滤行
this.tree.OptionsBehavior.EnableFiltering = true;//开启过滤功能 //初始化树节点选择事件
this.tree.FocusedNodeChanged += delegate (object sender, FocusedNodeChangedEventArgs e)
{
this.FocusedNodeChanged();
};
//树节点双击处理事件
this.tree.DoubleClick += (s, e) =>
{
if (this.tree.FocusedNode != null)
{
string ID = string.Concat(this.tree.FocusedNode.GetValue("Id"));
MessageDxUtil.ShowTips("Id=" + ID);
}
};
//编辑记录失去焦点后校验处理
this.tree.ValidateNode += (s, e) =>
{
Console.WriteLine(this.tree.FocusedNode.GetValue("Name"));
};
}

实现类似GridView的嵌套列表展示的TreeList界面效果如下所示。

2、TreeListLookUpEdit控件绑定操作

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

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

对于下拉的树形列表,虽然这个控件比TreeList更复杂一些,它是下拉列表和TreeList的整合体,不过我们也可以用类似的扩展函数方法,来简单的实现数据的绑定展示。

如对于常规的数据绑定,我们大概的代码如下所示。

//TreeListLookupEdit数据绑定
//this.txtProjectList3.Properties.TreeList.OptionsView.ShowCheckBoxes = true;
this.txtProjectList3.Properties.DataSource = list;
this.txtProjectList3.Properties.ValueMember = "Value";
this.txtProjectList3.Properties.DisplayMember = "Text";
this.txtProjectList3.Properties.TreeList.Columns.Clear();
for (int i = 0; i < columns.Count; i++)
{
this.txtProjectList3.Properties.TreeList.CreateColumn(columns[i].FieldName, columns[i].Caption,
columns[i].Width, true);
}
this.txtProjectList3.Properties.TreeList.InitTree(null, null, null, true, true); this.txtProjectList3.Properties.ImmediatePopup = true;
this.txtProjectList3.Properties.TextEditStyle = TextEditStyles.Standard;
this.txtProjectList3.Properties.PopupWidthMode = DevExpress.XtraEditors.PopupWidthMode.ContentWidth;
this.txtProjectList3.Properties.PopupFormSize = new System.Drawing.Size(this.txtProjectList3.Width, 300);
this.txtProjectList3.Properties.TreeList.IndicatorWidth = 40;
this.txtProjectList3.Properties.TreeList.CustomDrawNodeIndicator += (s, ee) =>
{
if (ee.IsNodeIndicator)
{
var index = ee.Node.TreeList.GetVisibleIndexByNode(ee.Node);
ee.Info.DisplayText = (index + 1).ToString();
}
};

对于常规的列表绑定,我们可以用简单的一个扩展函数实现,如下所示。

    //常规类别绑定
this.txtProjectList4.BindDictItems(list, "Text", "Value", true, columns.ToArray());

就可以实现常规的界面效果处理。

对于树形列表,我们需要设置属性的ID和PID,以及一些显示的列属性,那么也可以增加更多的参数来实现。

var dictTypeColumns = new List<LookUpColumnInfo>()
{
new LookUpColumnInfo("Id", "Id"),
new LookUpColumnInfo("Name", "字典类别名称")
};
treeListLookUp.BindDictItems(result.Items, "Name", "Id", true, false, "Id", "PID", null, true, true, true, false, dictTypeColumns.ToArray());

因此嵌套列表就可以正常的展示出层次关系了

因此我们把扩展方法,放到静态类里面就可以了,方法封装如下所示

       /// <summary>
/// 绑定TreeListLookUpEdit控件的数据源(完整版)
/// </summary>
/// <param name="lookup">控件对象</param>
/// <param name="dataSource">数据源</param>
/// <param name="displayMember">显示字段</param>
/// <param name="valueMember">值字段</param>
/// <param name="showRowIndicator">是否显示序号</param>
/// <param name="showCheckbox">是否显示复选框</param>
/// <param name="keyFieldName">设置父子递归关系字段-子字段,不指定则使用valueMember</param>
/// <param name="parentFieldName">设置父子递归关系字段-父字段,不指定则不嵌套展示</param>
/// <param name="rootValue">根节点的值</param>
/// <param name="editable">树节点是否可以编辑</param>
/// <param name="showColumnHeader">是否显示列头</param>
/// <param name="oddEvenRowColor">是否奇偶行不同颜色</param>
/// <param name="allowDrop">是否运行拖动列</param>
/// <param name="lookUpColumnInfos">显示的列</param>
/// <returns></returns>
public static object BindDictItems(this TreeListLookUpEdit lookup, object dataSource, string displayMember, string valueMember, bool showRowIndicator = true,
bool showCheckbox = false, string keyFieldName = null, string parentFieldName = null, string rootValue = null, bool editable = true,
bool showColumnHeader = false, bool oddEvenRowColor = true, bool allowDrop = false,
params LookUpColumnInfo[] lookUpColumnInfos)
{
lookup.Properties.DataSource = dataSource;
lookup.Properties.DisplayMember = displayMember;
lookup.Properties.ValueMember = valueMember;
lookup.Properties.TreeList.OptionsView.ShowCheckBoxes = showCheckbox; lookup.Properties.TreeList.Columns.Clear();
for (int i = 0; i < lookUpColumnInfos.Length; i++)
{
lookup.Properties.TreeList.CreateColumn(lookUpColumnInfos[i].FieldName, lookUpColumnInfos[i].Caption,
lookUpColumnInfos[i].Width, true);
} //初始化树的样式和特性
//keyFieldName = !string.IsNullOrWhiteSpace(keyFieldName) ? keyFieldName : valueMember;//如果不指定,采用valueMember
lookup.Properties.TreeList.InitTree(keyFieldName, parentFieldName, rootValue, editable, showColumnHeader, oddEvenRowColor, allowDrop);
lookup.Properties.PopupFormSize = new System.Drawing.Size(lookup.Width, 300); lookup.Properties.ImmediatePopup = true;
lookup.Properties.TextEditStyle = TextEditStyles.Standard; if (showRowIndicator)
{
lookup.Properties.TreeList.IndicatorWidth = 40;
//重写序号显示,默认不显示数值
lookup.Properties.TreeList.CustomDrawNodeIndicator += (s, ee) =>
{
if (ee.IsNodeIndicator)
{
var index = ee.Node.TreeList.GetVisibleIndexByNode(ee.Node);
ee.Info.DisplayText = (index + 1).ToString();
}
};
} return dataSource;
}

通过扩展方法的方式,可以简化界面的处理代码,同时利于我们在项目开发的时候,快速的实现相关的效果,而不需要过多的中断查找相关的界面控件属性。

有几篇类似的文章,可供参考:

在Winform开发中,我们使用的几种下拉列表展示字典数据的方式

在Winform开发框架中下拉列表绑定字典以及使用缓存提高界面显示速度

在各种开发项目中使用公用类库的扩展方法,通过上下文方式快速调用处理函数

使用扩展函数方式,在Winform界面中快捷的绑定树形列表TreeList控件和TreeListLookUpEdit控件的更多相关文章

  1. 在Winform界面中实现对多文档窗体的参数传值

    在Winform界面中窗体我们一般使用多文档进行展示,也就是类似一般的选项卡的方式可以加载多个窗体界面.一般来说,我们如果打开新的窗体,给窗体传递参数是很容易的事情,但是在框架层面,一般的窗体是通过动 ...

  2. 在Winform界面中使用DevExpress的TreeList实现节点过滤查询的两种方式

    在我较早的一篇随笔<在DevExpress程序中使用TeeList控件以及节点查询的处理>中,介绍了在树形列表TreeList控件上面,利用SearchControl实现节点的模糊查询过滤 ...

  3. Winform界面中实现菜单列表的动态个性化配置管理

    在我们一般的应用系统里面,由于系统是面向不同类型的用户,我们所看到的菜单会越来越多,多一点的甚至上百个,但是我们实际工作接触的菜单可能就是那么几个,那么对于这种庞大的菜单体系,寻找起来非常不便.因此对 ...

  4. Winform界面中主从表编辑界面的快速处理

    在Winform开发中,我们往往除了常规的单表信息录入外,有时候设计到多个主从表的数据显示.编辑等界面,单表的信息一般就是控件和对象实体一一对应,然后调用API保存即可,主从表就需要另外特殊处理,本随 ...

  5. Winform界面中实现通用工具栏按钮的事件处理

    在一个给客户做的项目中,界面要求修改增加通用工具栏按钮的事件处理,也就是在主界面中放置几个固定的功能操作按钮,打开不同的页面的时候,实现对应页面的功能处理,这种和我标准的界面处理方式有所不同,标准的列 ...

  6. C# Winform 界面中各控件随着窗口大小变化

    在做一项工程中,由于不确定目标平台的分辨率,而正常使用要求铺满整个屏幕,所以界面中的各个控件必须能够适应窗口的变化. 首先想到的就是控件的百分比布局,但是再尝试写了几个控件的Location和Size ...

  7. 调整代码生成工具Database2Sharp的Winform界面生成,使其易于列表工具栏的使用。

    在Winform界面开发的时候,有时候我们客户喜欢把功能放在列表界面的顶部,这样界面和功能整齐放置,也是一种比较美观的方式,基于这种方式的考虑,改造了代码生成工具的Winform界面生成规则,把增删改 ...

  8. Winform开发框架之权限管理系统改进的经验总结(1)-TreeListLookupEdit控件的使用

    最近一直在做一些技术性的研究和框架改进工作,博客也落下好几天没有更新了,也该是时候静下心来,总结这段时间的一些技术改进的经验了.和上一阶段的CRM系统开发和技术研究一样,我都喜欢在一个项目或者模块完成 ...

  9. 原创+部分引用啦:C# Winform界面中的分隔线问题

    C sharp 中Winform中的控件很多,一个小小的问题居然会绕上一个小弯子,做界面的时候, 你需要在界面上弄一条分隔线,把相关的功能分隔开来,结果原来在其它 IDE编辑器里很容易实现的这个功能, ...

  10. WinForm界面中快捷键设置

    这是对整个界面的快捷键的设置,比如查询,保存. 1 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if ...

随机推荐

  1. Linux子系统之【内存管理】

    1.内存管理的意义? 内存是进程运行的地方,相当于是战场.完善的机制能让进程多快好省地运行. 2.原始内存管理是怎么样的? 简陋(直接运行在物理内存上).不安全(无隔离,无权限) 缺点:容易出错,进程 ...

  2. EVE如何提升名望值

    目录 背景介绍 简介 名望值划分 军团名望值 利弊 背景介绍 ​ 玩eve将近3个星期,开着毒蜥级刷1级代理人任务感觉没有一点难度,想尽快刷3.4级代理任务,而我目前能够接到的最高代理任务也就才1级. ...

  3. 解决idea xml文件中的中文注释乱码

    今天用idea编译xml文件的时候报错了,打开编译好的xml文件发现是中文乱码问题,按照百度上靠前的办法设置了一下,并没有解决乱码问题,在当前项目中直接设置就是不生效,最后删掉编译好的 target/ ...

  4. AWS、谷歌云、Azure:云计算安全功能比较

    每个云平台提供给客户用以保护其云资产安全工具和安全功能都不一样. 公有云安全建立在共担责任概念基础之上:大型云服务提供商交付安全超大规模环境,但保护推上云端一切是客户自己责任.对企业而言,这种安全责任 ...

  5. vs2019配置boost库(转载)

    网址:https://blog.csdn.net/qq_42214953/article/details/105087015 关于途中的执行文件,可以使用b2.exe,不用跟着教程走. 如果本来就有b ...

  6. python中时间的datatime的模块

    datetime.datetime.now().strftime('%Y-%m-%d-%H_%M_%S')1.python datetime模块用strftime 格式化时间 import datet ...

  7. syn flood

    from scapy.all import * import random # 生成随机的IP def randomIP(): ip = ".".join(map(str, (ra ...

  8. Pinia使用技巧

    vue2使用的vuex,是一个状态管理器,现在vue3出了最新的pinia,今年偿试一下. 首先是安装,这里要注意一下,有一个持久化插件,如果不用的话,页面一刷新,状态会消失. npm install ...

  9. 声网深度学习时序编码器的资源预测实践丨Dev for Dev 专栏

    本文为「Dev for Dev 专栏」系列内容,作者为声网大后端智能运营算法团队 算法工程师@黄南薰. 随着深度学习技术的发展,编码器的结构在构建神经网络中成为了热门之选,在计算机视觉领域有众多成功案 ...

  10. C#笔记之泛型

    泛型是C#中应用极为广泛的一种语法,本篇文章将详细介绍泛型的定义.使用.性能等. 一.什么是泛型 首先需要记住的是,泛型是.NET 2.0推出的语法,这样的话,泛型基本可以用于所有程序的开发,而不需要 ...