using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Channels; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; using System.Xml.Linq; using static System.Runtime.InteropServices.JavaScript.JSType; namespace Ramitta { public partial class winTreeList : UserControl { public winTreeList() { InitializeComponent(); Nodes = new ObservableCollection(); } #region 公共属性 /// /// 获取或设置树形列表的节点集合 /// public ObservableCollection Nodes { get { return (ObservableCollection)GetValue(NodesProperty); } set { SetValue(NodesProperty, value); } } public static readonly DependencyProperty NodesProperty = DependencyProperty.Register("Nodes", typeof(ObservableCollection), typeof(winTreeList), new PropertyMetadata(null, OnNodesChanged)); private static void OnNodesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = (winTreeList)d; control.treeView.ItemsSource = control.Nodes; } #endregion #region 公共方法 #region 增 public LabelTreeNode AddLabelNode(string text, TreeNode? parent = null) { var node = new LabelTreeNode { Text = text }; AddNode(node, parent); return node; } public CheckboxTreeNode AddCheckboxNode(string text, string? tag=null, bool isChecked = false, TreeNode? parent = null) { var node = new CheckboxTreeNode { Text = text, IsChecked = isChecked, Tag = tag ?? text }; AddNode(node, parent); return node; } public ComboboxTreeNode AddComboboxNode(string text, string[]? item=null, TreeNode? parent = null) { var node = new ComboboxTreeNode { Text = text, ComboBoxItems = new ObservableCollection(item ?? []), }; AddNode(node, parent); return node; } #endregion #region 查(这里面的函数下一个版本全被杀) /// /// 获取所有被勾选的Checkbox节点的Tag /// /// 当前节点集合 /// 被勾选Checkbox节点的Tag列表 public List GetCheckedCheckboxTags(IEnumerable nodes) { var tags = new List(); foreach (var node in nodes) { if (node is CheckboxTreeNode checkboxNode && checkboxNode.IsChecked) { tags.Add(checkboxNode.Tag); } // 递归查找子节点 tags.AddRange(GetCheckedCheckboxTags(node.Children)); } return tags; } /// /// 获取所有被勾选的Checkbox节点的Tag /// /// 当前节点集合 /// 被勾选Checkbox节点的Tag列表 public List GetNoCheckedCheckboxTags(IEnumerable nodes) { var tags = new List(); foreach (var node in nodes) { if (node is CheckboxTreeNode checkboxNode && checkboxNode.IsChecked != true) { tags.Add(checkboxNode.Tag); } // 递归查找子节点 tags.AddRange(GetCheckedCheckboxTags(node.Children)); } return tags; } public List GetNoCheckBoxNodes(bool check) { return GetAllNodes().OfType(). Where(n => (check ? n.IsChecked : !n.IsChecked) ).ToList(); } /// /// 获取指定Label节点下所有被勾选的Checkbox节点的Tag列表 /// /// Label节点的名称 /// 被勾选Checkbox节点的Tag列表 public List GetCheckboxTagsUnderLabelNode(string labelNodeName) { var tags = new List(); List getTreeNode = FindTreeNodes(Nodes, labelNodeName); var labelNode = getTreeNode.Count != 0 ? getTreeNode[0] : null; if (labelNode != null) { tags.AddRange(GetCheckedCheckboxTags(labelNode.Children)); } return tags; } #endregion #region 查 /// /// 按照指定key路径查找元素(返回一个) /// public TreeNode? FindArgvNode(IEnumerable nodes, List key) { if (nodes == null) nodes = Nodes; if(key.Count == 0) return null; foreach (var node in nodes) { if (node is TreeNode obj && obj.Text == key[0] && key.Count==1) { // 最后的层级,且符合指标的第一个值 return obj; } var foundNode = FindArgvNode(node.Children, key.Skip(1).ToList()); if (foundNode != null) { return foundNode; } } return null; } public List? FindTreeNodes(IEnumerable? nodes, string key) where xTreeNode : class { List? result = null; if (nodes == null) nodes = Nodes; foreach (var node in nodes) { // 检查当前节点是否匹配 if (node.Text == key && node is xTreeNode) { if(result == null) result = new List(); result.Add(node as xTreeNode); } // 跳过空子 if (node.Children.Count == 0) continue; // 迭代下层 List? res = FindTreeNodes(node.Children, key); if (res == null)continue; if (res.Count != 0) { if (result == null) result = new List(); result.AddRange(res); } } return result; } // 改这个玩意 public xControl? Find(IEnumerable? nodes, string key) where xTreeNode : class where xControl : DependencyObject { if (nodes == null) nodes = Nodes; xTreeNode? targetNode = FindTreeNodes(nodes, key)[0]; if (targetNode == null) return null; else return To(targetNode); } public xControl? To(xTreeNode node) where xTreeNode : class where xControl : DependencyObject { var treeViewItem = FindTreeViewItem(treeView, node); if (treeViewItem != null) { xControl xCtrl = FindVisualChild(treeViewItem); if (xCtrl != null) { return xCtrl; } } return null; } private TreeViewItem? FindTreeViewItem(ItemsControl container, T xTreeNode) where T : class { for (int i = 0; i < container.Items.Count; i++) { TreeViewItem? item = container.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem; if (item != null) { if (item.DataContext == xTreeNode) { return item; } TreeViewItem? childItem = FindTreeViewItem(item, xTreeNode); if (childItem != null) { return childItem; } } } return null; } private T FindVisualChild(DependencyObject parent) where T : DependencyObject { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) { DependencyObject child = VisualTreeHelper.GetChild(parent, i); if (child is T) { return (T)child; } T childOfChild = FindVisualChild(child); if (childOfChild != null) { return childOfChild; } } return null; } public JObject JsonPrint(IEnumerable? nodes, int loop = 0) { // 如果传入的节点为空,使用默认的 Nodes 集合 if (nodes == null) nodes = Nodes; JObject resultObject = new JObject(); // 为每个节点构建一个 JObject foreach (var node in nodes) { JObject nodeObject = new JObject(); // 为当前节点添加基本信息 nodeObject["Type"] = node.GetType().Name; if (node.GetType() == typeof(CheckboxTreeNode)) { nodeObject["IsChecked"] = (node as CheckboxTreeNode)?.IsChecked.ToString(); } if (node.GetType() == typeof(ComboboxTreeNode)) { var target = node as ComboboxTreeNode; nodeObject["SelectedItem"] = target?.SelectedItem.ToString(); } // 处理子节点 if (node.Children.Count > 0) { // 递归调用以处理子节点,并将结果放在 "child" 属性下 JObject childrenObject = JsonPrint(node.Children, loop + 1); nodeObject["child"] = childrenObject; } // 使用节点文本作为属性名,将当前节点对象添加到结果中 resultObject.Add(node.Text, nodeObject); } // 返回结果对象 return resultObject; } #endregion #region 删 #endregion #region 动力学 public void Clear() { Nodes.Clear(); } public void ExpandAll() { foreach (var node in Nodes) { ExpandNode(node); } } public void CollapseAll() { foreach (var node in Nodes) { CollapseNode(node); } } #endregion #endregion #region 私有方法 private void AddNode(TreeNode node, TreeNode parent) { if (parent == null) { Nodes.Add(node); } else { parent.Children.Add(node); } } private IEnumerable GetAllNodes() { return GetAllNodes(Nodes); } private IEnumerable GetAllNodes(IEnumerable nodes) { foreach (var node in nodes) { yield return node; foreach (var child in GetAllNodes(node.Children)) { yield return child; } } } private void ExpandNode(TreeNode node) { var container = treeView.ItemContainerGenerator.ContainerFromItem(node) as TreeViewItem; if (container != null) { container.IsExpanded = true; } foreach (var child in node.Children) { ExpandNode(child); } } private void CollapseNode(TreeNode node) { var container = treeView.ItemContainerGenerator.ContainerFromItem(node) as TreeViewItem; if (container != null) { container.IsExpanded = false; } foreach (var child in node.Children) { CollapseNode(child); } } #endregion } #region 数据模型 public abstract class TreeNode { public TreeNode() { Children = new ObservableCollection(); } public string Text { get; set; } public ObservableCollection Children { get; set; } } /// /// Label类型的树节点 /// public class LabelTreeNode : TreeNode { } /// /// Label类型的树节点 /// public class ComboboxTreeNode : TreeNode { public string SelectedItem { get; set; } public ObservableCollection ComboBoxItems { get; set; } = new ObservableCollection(); } /// /// Checkbox类型的树节点 /// public class CheckboxTreeNode : TreeNode { public string Tag { get; set; } private bool _isChecked; public bool IsChecked { get { return _isChecked; } set { if (_isChecked != value) { _isChecked = value; } } } } #endregion }