WPF中使用ListView封装组合控件TreeView+DataGrid-粉丝专栏

        wpf的功能非常强大,很多控件都是原生的,但是要使用TreeView+DataGrid的组合,就需要我们自己去封装实现。

我们需要的效果如图所示:

这2个图都是第三方控件自带的,并且都是收费使用。

现在我们就用原生的控件进行封装一个。

本文源码效果截图,(搞了好几天,的确有难度,所以源码也收费,便宜,赚点辛苦费)

功能如上图所示, 目前基本上把常用的样式都实现了,购买源码后,可以自行修改样式。

首先说明一下,实现上面的效果,有3种方法

第一种:技术的选择是TreeView。

WPF中使用TreeView封装组合控件TreeView+DataGrid-粉丝专栏-CSDN博客

第二种:技术的选择是DataGrid。

WPF中使用DataGrid封装组合控件TreeView+DataGrid-粉丝专栏-CSDN博客

第三种:技术的选择是ListView。(也就是本文的演示)

本文演示的是ListView的实现。

1.首先建立一个wpf程序

2.封装TreeList.cs

namespace ListView.TreeDataGrid
{using System;using System.Collections;using System.Collections.Generic;using System.Collections.ObjectModel;using System.Collections.Specialized;using System.Linq;using System.Windows;using System.Windows.Controls;using System.Windows.Controls.Primitives;public class TreeList : ListView{#region Properties/// <summary>/// Internal collection of rows representing visible nodes, actually displayed in the ListView/// </summary>internal ObservableCollectionAdv<TreeNode> Rows{get;private set;}private ITreeModel _model;public ITreeModel Model{get { return _model; }set{if (_model != value){_model = value;_root.Children.Clear();Rows.Clear();CreateChildrenNodes(_root);}}}private TreeNode _root;internal TreeNode Root{get { return _root; }}public ReadOnlyCollection<TreeNode> Nodes{get { return Root.Nodes; }}internal TreeNode PendingFocusNode{get;set;}public ICollection<TreeNode> SelectedNodes{get{return SelectedItems.Cast<TreeNode>().ToArray();}}public TreeNode SelectedNode{get{if (SelectedItems.Count > 0)return SelectedItems[0] as TreeNode;elsereturn null;}}#endregionpublic TreeList(){Rows = new ObservableCollectionAdv<TreeNode>();_root = new TreeNode(this, null);_root.IsExpanded = true;ItemsSource = Rows;ItemContainerGenerator.StatusChanged += ItemContainerGeneratorStatusChanged;}void ItemContainerGeneratorStatusChanged(object sender, EventArgs e){if (ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated && PendingFocusNode != null){var item = ItemContainerGenerator.ContainerFromItem(PendingFocusNode) as TreeListItem;if (item != null)item.Focus();PendingFocusNode = null;}}protected override DependencyObject GetContainerForItemOverride(){return new TreeListItem();}protected override bool IsItemItsOwnContainerOverride(object item){return item is TreeListItem;}protected override void PrepareContainerForItemOverride(DependencyObject element, object item){var ti = element as TreeListItem;var node = item as TreeNode;if (ti != null && node != null){ti.Node = item as TreeNode;base.PrepareContainerForItemOverride(element, node.Tag);}}internal void SetIsExpanded(TreeNode node, bool value){if (value){if (!node.IsExpandedOnce){node.IsExpandedOnce = true;node.AssignIsExpanded(value);CreateChildrenNodes(node);}else{node.AssignIsExpanded(value);CreateChildrenRows(node);}}else{DropChildrenRows(node, false);node.AssignIsExpanded(value);}}internal void CreateChildrenNodes(TreeNode node){var children = GetChildren(node);if (children != null){int rowIndex = Rows.IndexOf(node);node.ChildrenSource = children as INotifyCollectionChanged;foreach (object obj in children){TreeNode child = new TreeNode(this, obj);child.HasChildren = HasChildren(child);node.Children.Add(child);}Rows.InsertRange(rowIndex + 1, node.Children.ToArray());}}private void CreateChildrenRows(TreeNode node){int index = Rows.IndexOf(node);if (index >= 0 || node == _root) // ignore invisible nodes{var nodes = node.AllVisibleChildren.ToArray();Rows.InsertRange(index + 1, nodes);}}internal void DropChildrenRows(TreeNode node, bool removeParent){int start = Rows.IndexOf(node);if (start >= 0 || node == _root) // ignore invisible nodes{int count = node.VisibleChildrenCount;if (removeParent)count++;elsestart++;Rows.RemoveRange(start, count);}}private IEnumerable GetChildren(TreeNode parent){if (Model != null)return Model.GetChildren(parent.Tag);elsereturn null;}private bool HasChildren(TreeNode parent){if (parent == Root)return true;else if (Model != null)return Model.HasChildren(parent.Tag);elsereturn false;}internal void InsertNewNode(TreeNode parent, object tag, int rowIndex, int index){TreeNode node = new TreeNode(this, tag);if (index >= 0 && index < parent.Children.Count)parent.Children.Insert(index, node);else{index = parent.Children.Count;parent.Children.Add(node);}Rows.Insert(rowIndex + index + 1, node);}}
}

3.TreeStyles.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:ListView.TreeDataGrid"><Style TargetType="{x:Type local:TreeListItem}"><Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/><Style.Triggers><!--隔行换色--><Trigger Property="ListBox.AlternationIndex"  Value="0" ><Setter Property="Background" Value="#e7e7e7" /></Trigger><Trigger Property="ListBox.AlternationIndex" Value="1" ><Setter Property="Background" Value="#f2f2f2" /></Trigger><Trigger Property="IsMouseOver" Value="True"><Setter Property="Background" Value="Orange"/></Trigger><Trigger Property="IsSelected" Value="True"><!--选中的行颜色--><Setter Property="Background" Value="Aqua"/></Trigger></Style.Triggers></Style><Style x:Key="TreeListItemNodeStyle" TargetType="{x:Type local:TreeListItem}" ><Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/><Setter Property="FocusVisualStyle" Value="{x:Null}"/><Setter Property="Template"><Setter.Value><ControlTemplate><ContentPresenter Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" /><ControlTemplate.Triggers><Trigger Property="UIElement.IsEnabled" Value="False"><Setter Property="TextElement.Foreground"><Setter.Value><DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" /></Setter.Value></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>
</ResourceDictionary>

4.最终源码实例

说明: 使用ListView封装的时候,难度最大,或者没有找到最好的方法实现。

需要源码请联系我。

本文来源:

WPF中使用ListView封装组合控件TreeView+DataGrid-粉丝专栏-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/223146.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构入门精讲 | 第十三篇】考研408、公司面试树专项练习(二)

在上一篇中我们进行了树的判断题、选择题、填空题专项练习&#xff0c;在这一篇中我们将进行编程题的相关练习。 目录 编程题R7-1 目录树R7-1 是否同一棵二叉搜索树R7-2 二叉搜索树的结构R7-3 平衡二叉树的根R7-1 完全二叉搜索树R7-1 修理牧场R7-2 嘴强王者R7-3 房屋分拆R7-4 动…

Django 简单图书管理系统

一、图书需求 1. 书籍book_index.html中有超链接&#xff1a;查看所有的书籍列表book_list.html页面 2. 书籍book_list.html中显示所有的书名&#xff0c;有超链接&#xff1a;查看本书籍详情book_detail.html(通过书籍ID)页面 3. 书籍book_detail.html中书的作者和出版社&…

Stable Diffusion系列(三):网络分类与选择

文章目录 网络分类模型基座模型衍生模型二次元模型2.5D模型写实风格模型 名称解读 VAELora嵌入文件放置界面使用 网络分类 当使用SD webui绘图时&#xff0c;为了提升绘图质量&#xff0c;可以多种网络混合使用&#xff0c;可选的网络包括了模型、VAE、超网络、Lora和嵌入。 …

Vue3视图渲染技术(2)

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

kubernetes集群 应用实践 kafka部署

kubernetes集群 应用实践 kafka部署 零.1、环境说明 零.2、kafka架构说明 zookeeper在kafka集群中的作用 一、Broker注册 二、Topic注册 三、Topic Partition选主 四、生产者负载均衡 五、消费者负载均衡 一、持久化存储资源准备 1.1 创建共享目录 [rootnfsserver ~]# mkdir -…

医学实验室检验科LIS信息系统源码

实验室信息管理是专为医院检验科设计的一套实验室信息管理系统&#xff0c;能将实验仪器与计算机组成网络&#xff0c;使病人样品登录、实验数据存取、报告审核、打印分发&#xff0c;实验数据统计分析等繁杂的操作过程实现了智能化、自动化和规范化管理。 实验室管理系统功能介…

阿里云ECS配置IPv6后,如果无法访问该服务器上的网站,可检查如下配置

1、域名解析到这个IPv6地址,同一个子域名可以同时解析到IPv4和IPv6两个地址&#xff0c;这样就可以给网站配置ip4和ipv6双栈&#xff1b; 2、在安全组规则开通端口可访问&#xff0c;设定端口后注意授权对象要特殊设置“源:::/0” 3、到服务器nginx配置处&#xff0c;增加端口…

二值选择模型-以stata为工具

二值选择模型-以stata为工具 文章目录 1. 命令语法2. 模型 代码示例2.1 读取数据2.2 建立模型2.3 数据预测1. 命令语法 二值选择模型是计量经济学中常用的一种模型,用于处理因变量为二值(0或1)的情况。 这种模型通常用来研究个体在面临两个或多个离散选择时的决策行为。其中…

Mybatis之增删改查

目录 一、引言 二、Mybatis——增 举例&#xff1a;添加用户 三、Mybatis——删 举例&#xff1a;删除用户 四、Mybatis——改 举例&#xff1a;修改用户 五、Mybatis——查 六、注意 END&#xff1a; 一、引言 书接上回&#xff0c;我们在了解完mybatis之后&#xff0c;肯…

会员管理怎么做?

会员管理是企业运营的重要组成部分&#xff0c;它涉及到会员的招募、维护、激励、保留、转化等多个环节。下面&#xff0c;我们将结合具体的案例&#xff0c;详细介绍会员管理的具体做法。 首先&#xff0c;会员的招募是会员管理的第一步 企业需要通过各种方式吸引消费者成为会…

【大数据】NiFi 中的 Controller Service

NiFi 中的 Controller Service 1.Service 简介1.1 Controller Service 的配置1.1.1 SETTING 基础属性1.1.2 PROPERTIES 使用属性1.1.3 COMMENT 页签 1.2 Service 的使用范围 2.全局参数配置3.DBCPConnectionPool 的使用样例4.在 ExcuseGroovyScript 组件中使用 Service 1.Servi…

【Prometheus|报错】Out of bounds

【背景】进入Prometheus地址的9090端口&#xff0c;pushgateway&#xff08;0/1&#xff09;error : out of bounds 【排查分析】 1、out of bounds报错&#xff0c;是由于Prometheus向tsdb存数据出错&#xff0c;与最新存数据的时间序列有问题&#xff0c;有可能当前时间与最…

步兵 cocos2dx 加密和混淆

文章目录 摘要引言正文代码加密具体步骤代码加密具体步骤测试和配置阶段IPA 重签名操作步骤 总结参考资料 摘要 本篇博客介绍了针对 iOS 应用中的 Lua 代码进行加密和混淆的相关技术。通过对 Lua 代码进行加密处理&#xff0c;可以确保应用代码的安全性&#xff0c;同时提高性…

小白入门之安装MYSQL

重生之我在大四学JAVA 第三章 安装MYSQL 把MySQL复制到要安装的路径下解压 到解压后的bin路径下复制路径 接着以“管理员”身份打开命令行(如下图所示) 注意&#xff1a;一定要是管理员身份&#xff0c;否则由于后续部分命令需要权限&#xff0c;出现错误&#xff01; 转到…

C# .Net学习笔记—— Expression 表达式目录树

目录 一、什么是表达式目录树 二、Func与Expression的区别 1、Func是方法 3、使用ILSpy反编译解析看一下 ​编辑 ​编辑 4、拼装练习 5、动态生成硬编码&#xff08;通用、性能好&#xff09; 5、表达式目录树动态生成的用途&#xff1a; 6、递归解析表达式目录树 7、…

凸优化 2:如何判定凸函数?

凸优化 2&#xff1a;如何判定凸函数&#xff1f; 如何判断一个目标函数是凸函数&#xff1f;如果是凸函数&#xff0c;那ta的定义域是凸集合 一个函数求俩次梯度&#xff0c;大于等于0&#xff0c;那这个函数就是一个凸函数在同样条件下&#xff0c;怎么设计为凸函数模型&…

Go后端开发 -- 环境搭建

Go后端开发 – 环境搭建 文章目录 Go后端开发 -- 环境搭建一、环境配置二、IDE的选择三、使用go mod构建项目1.初始化项目2.添加依赖项3.运行项目 四、环境报错1.VS Code中gopls报错 一、环境配置 Go官网下载地址&#xff1a;https://golang.org/dl/ https://go.dev/dl/ Go官方…

安装nodejs,配置环境变量并将npm设置淘宝镜像源

安装nodejs并将npm设置淘宝镜像源 1. 下载nodejs 个人不喜欢安装包&#xff0c;所以是下载zip包的方式。这里我下载的node 14解压包版本 下载地址如下&#xff1a;https://nodejs.org/dist/v14.15.1/node-v14.15.1-win-x64.zip 想要其他版本的小伙伴去https://nodejs.org/di…

nodejs+vue+ElementUi资源互助共享平台的设计

后台&#xff1a;管理员功能有个人中心&#xff0c;用户管理&#xff0c;卖家管理&#xff0c;咨询师管理&#xff0c;萌宝信息管理&#xff0c;幼儿知识管理&#xff0c;保姆推荐管理&#xff0c;音频资源管理&#xff0c;二手商品管理&#xff0c;商品分类管理&#xff0c;资…

第26关 K8s日志收集揭秘:利用Log-pilot收集POD内业务日志文件

------> 课程视频同步分享在今日头条和B站 大家好&#xff0c;我是博哥爱运维。 OK&#xff0c;到目前为止&#xff0c;我们的服务顺利容器化并上了K8s&#xff0c;同时也能通过外部网络进行请求访问&#xff0c;相关的服务数据也能进行持久化存储了&#xff0c;那么接下来…