CommonTree
时间:2021-08-19
本文章向大家介绍CommonTree,主要包括CommonTree使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
树结构的数据显示,
满足一般的数据加载、查询、刷新、勾选并获取勾选项
xaml
<UserControl x:Class="ZHHT.Themes.Controls.Wpf.CommonTree"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
d:DesignHeight="450" d:DesignWidth="300">
<UserControl.Resources>
<HierarchicalDataTemplate x:Key="ItemNode" ItemsSource="{Binding Children,Mode=TwoWay}">
<Grid Background="Transparent">
<StackPanel MinHeight="25" Orientation="Horizontal" Background="Transparent"
HorizontalAlignment="Left" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" IsChecked="{Binding IsCheck, Mode=OneWay}" Tag="{Binding Node}"
Checked="ItemNode_Checked" Unchecked="ItemNode_Unchecked">
</CheckBox>
<TextBlock Grid.Column="1" Text="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="3 0" />
<TextBlock Grid.Column="2" Text="{Binding Remark}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="3 0" />
</Grid>
</StackPanel>
</Grid>
</HierarchicalDataTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" x:Name="txtSearchContent" KeyDown="TextBoxSearchContent_KeyDown"/>
<Button Grid.Column="1" Style="{DynamicResource MahApps.Styles.Button.Circle}" Content="{iconPacks:ForkAwesome Kind=Search}" ToolTip="查询" Width="30" Height="30" Margin="5" Click="ButtonSearch_Click"></Button>
<Button Grid.Column="2" Style="{DynamicResource MahApps.Styles.Button.Circle}" Content="{iconPacks:ForkAwesome Kind=Refresh}" ToolTip="刷新" Width="30" Height="30" Margin="5" Click="ButtonRefresh_Click"></Button>
</Grid>
<Grid Grid.Row="1" Name="grdSerchContent" Visibility="Collapsed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="1" Grid.Column="0" x:Name="lblSearch" />
<Button Grid.Row="1" Grid.Column="1" Style="{DynamicResource ButtonICOStyle}" Content="{iconPacks:Modern Kind=ArrowDown}" Width="30" Height="30" Click="ButtonNext_Click"></Button>
<Button Grid.Row="1" Grid.Column="2" Style="{DynamicResource ButtonICOStyle}" Content="{iconPacks:Modern Kind=ArrowUp}" Width="30" Height="30" Click="ButtonPre_Click"></Button>
</Grid>
<TreeView Grid.Row="2" Name="treeFrameInfo" ItemsSource="{Binding TreeSource}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
BorderThickness="0"
ItemTemplate="{DynamicResource ItemNode}" Style="{DynamicResource TreeViewExpanded}"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode ="Standard">
</TreeView>
</Grid>
</UserControl>
cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
public partial class CommonTree : UserControl
{
private FrameTree _treeRoot;
private int _searchIndex = 0;
/// <summary>
/// 查询到的项目列表
/// </summary>
private List<FrameTree> _searchListItems;
/// <summary>
/// 查询到的项目结点
/// </summary>
private List<TreeViewItem> _searchTreeViewItems;
private TreeViewItemHelper _helper = null;
private Dictionary<FrameTree, List<FrameTree>> _dicGroupTarget = new Dictionary<FrameTree, List<FrameTree>>();
/// <summary>
/// 已经勾选的项目
/// </summary>
public List<FrameTree> SelectItems { get; set; }
/// <summary>
/// 树的数据源
/// </summary>
public List<FrameTree> DataSource
{
get => (List<FrameTree>)GetValue(DataSourceProperty);
set => SetValue(DataSourceProperty, value);
}
public static readonly DependencyProperty DataSourceProperty =
DependencyProperty.Register("DataSource", typeof(List<FrameTree>), typeof(CommonTree), new PropertyMetadata(null, OnDataSourceChanged));
private static void OnDataSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CommonTree ctl = (CommonTree)d;
ctl.OnDataSourceChanged(e.NewValue);
}
private void OnDataSourceChanged(object newValue)
{
if (newValue is List<FrameTree> list && list.Count > 0)
{
_treeRoot = list[0];
TreeClear();
}
}
/// <summary>
/// 刷新事件
/// </summary>
public event EventHandler TreeRefreshEvent;
public CommonTree()
{
InitializeComponent();
if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
return;
}
InitOther();
}
/// <summary>
/// 清空树的勾选项
/// </summary>
public void TreeClear()
{
SelectItems.Clear();
ChangeCheckState(_treeRoot, false);
}
private void TextBoxSearchContent_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Enter)
{
ButtonSearch_Click(null, null);
}
}
private void InitOther()
{
SelectItems = new List<FrameTree>();
_helper = new TreeViewItemHelper();
_searchListItems = new List<FrameTree>();
_dicGroupTarget = new Dictionary<FrameTree, List<FrameTree>>();
_searchTreeViewItems = new List<TreeViewItem>();
grdSerchContent.Visibility = Visibility.Collapsed;
}
private void ButtonSearch_Click(object sender, RoutedEventArgs e)
{
try
{
if (string.IsNullOrWhiteSpace(txtSearchContent.Text))
{
grdSerchContent.Visibility = Visibility.Collapsed;
return;
}
_helper.targetTreeViewItem.Clear();
_searchListItems.Clear();
_searchTreeViewItems.Clear();
_searchIndex = 0;
TreeViewItem root = treeFrameInfo.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem;
_searchListItems = SelectTreeItem(_treeRoot, txtSearchContent.Text);
for (int i = _searchListItems.Count - 1; i >= 0; i--)
{
if (_searchListItems[i].Parent == null)
{
_ = _searchListItems.Remove(_searchListItems[i]); //这个为空应该是城市.
}
}
IEnumerable<IGrouping<string, FrameTree>> targetTreeGroup = from g in _searchListItems group g by g.Parent.Guid;
if (_searchListItems != null && _searchListItems.Count > 0)
{
_dicGroupTarget.Clear();
foreach (IGrouping<string, FrameTree> item in targetTreeGroup)
{
//同一个父亲下的节点
List<FrameTree> tempFrameTree = _searchListItems.Where(a => a.Parent.Guid == item.Key).ToList();
_dicGroupTarget.Add(tempFrameTree[0].Parent, tempFrameTree);
}
_ = _helper.GetTreeViewItemsForFrameTree(root, txtSearchContent.Text, _dicGroupTarget);
_searchTreeViewItems = _helper.targetTreeViewItem;
if (_searchTreeViewItems != null && _searchTreeViewItems.Count > 0)
{
_searchTreeViewItems[_searchIndex].IsSelected = true;
_searchTreeViewItems[_searchIndex].IsExpanded = true;
_ = _searchTreeViewItems[_searchIndex].Focus();
grdSerchContent.Visibility = Visibility.Visible;
lblSearch.Content = string.Format("当前【{0}】,共【{1}】项", _searchIndex + 1, _searchTreeViewItems.Count);
}
}
else
{
grdSerchContent.Visibility = Visibility.Visible;
lblSearch.Content = string.Format("当前【{0}】,共【{1}】项", _searchIndex, _searchTreeViewItems.Count);
}
}
catch (Exception ex)
{
Console.WriteLine("搜索发生异常:" + ex.Message.ToString(), ex);
}
}
private void ButtonRefresh_Click(object sender, RoutedEventArgs e)
{
txtSearchContent.Clear();
SelectItems.Clear();
grdSerchContent.Visibility = Visibility.Collapsed;
_helper.ScrollToTop(treeFrameInfo);
TreeRefreshEvent?.Invoke(this, EventArgs.Empty);
}
private void ButtonNext_Click(object sender, RoutedEventArgs e)
{
if (_searchTreeViewItems != null)
{
_searchIndex++;
_searchIndex = Math.Min(_searchIndex, _searchTreeViewItems.Count - 1);
if (_searchTreeViewItems.Count > 0)
{
if (_searchTreeViewItems[_searchIndex].DataContext.ToString().Contains("DisconnectedItem"))
{
TreeViewItem root = treeFrameInfo.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem;
_helper.targetTreeViewItem.Clear();
if (_dicGroupTarget != null && _dicGroupTarget.Count > 0)
{
//重新虚化
_ = _helper.GetTreeViewItemsForFrameTree(root, txtSearchContent.Text, _dicGroupTarget);
}
_searchTreeViewItems = _helper.targetTreeViewItem;
}
_searchTreeViewItems[_searchIndex].IsSelected = true;
_searchTreeViewItems[_searchIndex].IsExpanded = true;
_ = _searchTreeViewItems[_searchIndex].Focus();
grdSerchContent.Visibility = Visibility.Visible;
lblSearch.Content = string.Format("当前【{0}】,共【{1}】项", _searchIndex + 1, _searchTreeViewItems.Count);
}
}
}
private void ButtonPre_Click(object sender, RoutedEventArgs e)
{
if (_searchTreeViewItems != null)
{
_searchIndex--;
_searchIndex = Math.Max(_searchIndex, 0);
if (_searchTreeViewItems.Count > 0)
{
if (_searchTreeViewItems[_searchIndex].DataContext.ToString().Contains("DisconnectedItem"))
{
TreeViewItem root = treeFrameInfo.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem;
_helper.targetTreeViewItem.Clear();
if (_dicGroupTarget != null && _dicGroupTarget.Count > 0)
{
//重新虚化
_ = _helper.GetTreeViewItemsForFrameTree(root, txtSearchContent.Text, _dicGroupTarget);
}
_searchTreeViewItems = _helper.targetTreeViewItem;
}
_searchTreeViewItems[_searchIndex].IsSelected = true;
_searchTreeViewItems[_searchIndex].IsExpanded = true;
_ = _searchTreeViewItems[_searchIndex].Focus();
grdSerchContent.Visibility = Visibility.Visible;
lblSearch.Content = string.Format("当前【{0}】,共【{1}】项", _searchIndex + 1, _searchTreeViewItems.Count);
}
}
}
private void Frame_Checked(object sender, RoutedEventArgs e)
{
if (sender is CheckBox checkedItem)
{
if (checkedItem.Tag is FrameTree node)
{
ChangeCheckState(node, true);
}
}
}
private void Frame_Unchecked(object sender, RoutedEventArgs e)
{
if (sender is CheckBox checkedItem)
{
if (checkedItem.Tag is FrameTree node)
{
ChangeCheckState(node, false);
}
}
}
private static int _count = 0;
private void ChangeCheckState(FrameTree node, bool state)
{
if (node.IsCheck != state)
{
if (state)
{
_count++;
SelectItems.Add(node);
}
else
{
_count--;
_ = SelectItems.RemoveAll(x => x.Guid == node.Guid);
}
Console.WriteLine($"{_count}: {node.Name}:{node.IsCheck}==>{state}");
if (node.Children != null)
{
foreach (FrameTree item in node.Children)
{
ChangeCheckState(item, state);
}
}
}
node.IsCheck = state;
}
private List<FrameTree> SelectTreeItem(FrameTree node, string name)
{
List<FrameTree> selects = new List<FrameTree>();
if (node.Name.Contains(name))
{
selects.Add(node);
}
for (int i = 0; i < node.Children.Count; i++)
{
FrameTree childrenNode = node.Children[i];
selects.AddRange(SelectTreeItem(childrenNode, name));
}
return selects;
}
}
其中,结构树的实体FrameTree,树的帮助类TreeViewItemHelper可自己定义实现,
demo
<wesson:CommonTree x:Name="CommonTreeInfo" TreeRefreshEvent="CommonTreeInfo_TreeRefreshEvent"/>
prism
<zhht:CommonTree Grid.Row="1" DataSource="{Binding TreeSource, Mode=TwoWay}" x:Name="CommonTreeInfo">
<b:Interaction.Triggers>
<b:EventTrigger EventName="TreeRefreshEvent">
<b:InvokeCommandAction Command="{Binding CommonTreeRefreshCommand}"/>
</b:EventTrigger>
</b:Interaction.Triggers>
</zhht:CommonTree>
// view
private void ButtonClear_Click(object sender, System.Windows.RoutedEventArgs e)
{
CommonTreeInfo.TreeClear();
}
private void ButtonGetData_Click(object sender, System.Windows.RoutedEventArgs e)
{
var btn = (Button)sender;
btn.CommandParameter = CommonTreeInfo.SelectItems;
}
// viewmodel
private List<FrameTree> _treeSource;
/// <summary>
/// 可绑定树的数据列表
/// </summary>
public List<FrameTree> TreeSource
{
get { return _treeSource; }
set { SetProperty(ref _treeSource, value); }
}
public DelegateCommand CommonTreeRefreshCommand { get; private set; }
public ctor()
{
TreeSource = new List<FrameTree>();
CommonTreeRefreshCommand = new DelegateCommand(CommonTree_Refresh);
}
private async Task DataBindAsync()
{
var response = // 异步获取数据
if (response != null)
{
var root = new FrameTree();
root = GetTreeFrameChildren(response, root);
TreeSource.Clear();
TreeSource = new List<FrameTree> { root };
}
}
private FrameTree GetTreeFrameChildren(object dto, FrameTree parentNode)
{
var node = new FrameTree();
node.Guid = dto.Guid;
node.Name = dto.Name;
node.OriginalSource = dto;
node.ParentGuid = parentNode.Guid;
node.Parent = parentNode;
if (dto.Children == null)
{
return node;
}
foreach (var item in dto.Children.OrderBy(o => o.Name))
{
node.Children.Add(GetTreeFrameChildren(item, node));
}
return node;
}
原文地址:https://www.cnblogs.com/wesson2019-blog/p/15161526.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Redis数据淘汰算法
- 无损失放大低分辨率图片
- Linux内存页分配策略
- socket接口层分析
- 数据存储方式——JSON、CSV、MongoDB、Redis、MySQL
- Spring Boot引入swagger-ui 后swagger-ui.html无法访问404
- 多路复用IO内幕
- Linux信号处理
- Shopify主题title/description等SEO设置
- Golang实现守护进程
- LaTeX简单常用方法笔记
- Convolution_model_Application_v1a
- Windows平台快速安装MongoDB和Robo 3T
- Linux内存管理 - slab分配器
- akka-grpc - 基于akka-http和akka-streams的scala gRPC开发工具