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.hqwc.cn/news/295350.html

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

相关文章

使用Springboot做测试的步骤详解

​ &#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试…

CV算法面试题学习

本文记录了CV算法题的学习。 CV算法面试题学习 点在多边形内&#xff08;point in polygon&#xff09;高斯滤波器 点在多边形内&#xff08;point in polygon&#xff09; 参考自文章1&#xff0c;其提供的代码没有考虑一些特殊情况&#xff0c;所以做了改进。 做法&#xff…

Zookeeper-应用实战

Zookeeper Java客户端实战 ZooKeeper应用的开发主要通过Java客户端API去连接和操作ZooKeeper集群。 ZooKeeper官方的Java客户端API。 第三方的Java客户端API&#xff0c;比如Curator。 ZooKeeper官方的客户端API提供了基本的操作:创建会话、创建节点、读取节点、更新数据、…

【Unity基础】9.地形系统Terrain

【Unity基础】9.地形系统Terrain 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity基础系列博客&#xff0c;所学知识来自B站阿发老师~感谢 &#xff08;一&#xff09;地形编辑器Terrain &#xff08;1&#xff09;创建地形 游戏场景中大多数的山川河流地表地貌都是基…

16-高并发-队列术

队列&#xff0c;在数据结构中是一种线性表&#xff0c;从一端插入数据&#xff0c;然后从另一端删除数据。 在我们的系统中&#xff0c;不是所有的处理都必须实时处理&#xff0c;不是所有的请求都必须实时反馈结果给用户&#xff0c;不是所有的请求都必须100%一次性处理成功…

数据结构(超详细讲解!!)第二十八节 排序

1.排序的几个基本概念 排序就是将一个数据元素&#xff08;或记录&#xff09;的任意序列&#xff0c;重新排列成一个按关键字有序的序列。 数据表(Data List) &#xff1a;待排序的数据对象的有限集合。 关键字(Key)&#xff1a;数据元素&#xff08;或记录&#xff09;中…

GPT2代码运行,个人文本生成助手,不依赖OpenAI API调用

0.前言: 感觉GPT很好玩,所以想要有个自己搭建GPT的写法,不依赖于OpenAI,需要翻墙太麻烦了,近日日本已经结合GPT4和机器,可以让他吓人,做出丰富的表情,如果自己训练的话,会塑造出什么样的机器人尚未可知…抱着好奇的心态,去github openai下载了个gpt2的模型来玩玩(其中遇到了许多…

HackTheBox - Medium - Linux - Sandworm (我的创作纪念日

Sandworm Sandworm 是一台中等难度的 Linux 机器&#xff0c;它托管了一个具有“PGP”验证服务的 Web 应用程序&#xff0c;该服务容易受到服务器端模板注入 &#xff08;SSTI&#xff09; 的攻击&#xff0c;导致“Firejail”监狱内的远程代码执行 &#xff08;RCE&#xff0…

C++内存管理和模板初阶

C/C内存分布 请看代码&#xff1a; int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int* ptr1 (int*)mallo…

【STM32】I2C通信

基本的任务是&#xff1a;通过通信线&#xff0c;实现单片机读写外挂模块寄存器的功能。其中至少要实现在指定位置写寄存器和在指定的位置读寄存器这两个功能。 异步时序的优点&#xff1a;省一根时钟线&#xff0c;节约资源&#xff1b;缺点&#xff1a;对事件要求严格&#…

【XR806开发板试用】通过http请求从心知天气网获取天气预报信息

1. 开发环境搭建 本次评测开发环境搭建在windows11的WSL2的Ubuntu20.04中&#xff0c;关于windows安装WSL2可以参考文章: Windows下安装Linux(Ubuntu20.04)子系统&#xff08;WSL&#xff09; (1) 在WSL的Ubuntu20.04下安装必要的工具的. 安装git: sudo apt-get install git …

基于SpringBoot实现的前后端分离书店项目,功能:注册登录、浏览商品、热门商品、购物车、购买、地址管理、密码管理等

一、项目简介 本项目主要基于SpringBoot、Mybatis-plus、MySQL、Redis实现的书店管理系统。 本系统是前后端分离的&#xff0c;分别由三个子项目构成&#xff1a;java服务端、用户浏览与购买的前端、管理员管理商品的前端 环境 java 1.8mysql8.0redisvue2.x 管理员子系统功…