using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; 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.Net.Mime.MediaTypeNames; using static System.Runtime.InteropServices.JavaScript.JSType; namespace Ramitta { public partial class winTreeList : UserControl, INotifyPropertyChanged { #region 初始化 public event PropertyChangedEventHandler? PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public winTreeList() { InitializeComponent(); Nodes = new ObservableCollection(); } #endregion #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 label = new Label() { Content = text, Foreground = Brushes.White }; var node = new LabelTreeNode { Text = text, obj = label }; AddNode(node, parent); return node; } public CheckboxTreeNode AddCheckboxNode(string text, string? tag = null, bool isChecked = false, TreeNode? parent = null) { var checkbox = new CheckBox() { Visibility = Visibility.Visible, IsChecked = isChecked, Content = text, Tag = tag ?? text, ToolTip = tag ?? text, Foreground = Brushes.White, VerticalAlignment = VerticalAlignment.Center }; var node = new CheckboxTreeNode { Text = text, obj = checkbox }; AddNode(node, parent); return node; } public RadioButtonTreeNode AddRadioButtonNode(string text, string? tag = null,string? GroupName = null, bool isChecked = false, TreeNode? parent = null) { var RadioButton = new RadioButton() { Visibility = Visibility.Visible, GroupName = GroupName, IsChecked = isChecked, Content = text, Tag = tag ?? text, ToolTip = tag ?? text, Foreground = Brushes.White, VerticalAlignment = VerticalAlignment.Center }; var node = new RadioButtonTreeNode { Text = text, obj = RadioButton }; AddNode(node, parent); return node; } public ComboboxTreeNode AddComboboxNode(string text, List? items = null, TreeNode? parent = null) { var combobox = new ComboBox() { Visibility = Visibility.Visible, SelectedIndex = 0, VerticalAlignment = VerticalAlignment.Center, MinWidth = 100 }; var node = new ComboboxTreeNode { Text = text, obj = combobox }; AddNode(node, parent); return node; } #endregion #region 查 public List FindAllTreeNodes( IEnumerable? nodes, Func predicate = null) where xTreeNode : class { var result = new List(); if (nodes == null) nodes = Nodes; foreach (var node in nodes) { // 检查当前节点是否匹配类型和条件 if (node is xTreeNode targetNode && (predicate == null || predicate(node))) { result.Add(targetNode); } // 递归查找子节点 if (node.Children.Count > 0) { var childResults = FindAllTreeNodes(node.Children, predicate); result.AddRange(childResults); } } return result; } #endregion #region 删 /// /// 从树中删除指定节点 /// /// 要删除的节点 /// 是否成功删除 public bool RemoveNode(TreeNode nodeToRemove) { if (nodeToRemove == null) return false; // 如果节点有父节点,从父节点的 Children 中删除 if (nodeToRemove.Parent != null) { return nodeToRemove.Parent.Children.Remove(nodeToRemove); } // 如果是根节点,从 Nodes 集合中删除 else { return Nodes.Remove(nodeToRemove); } } /// /// 批量删除多个节点 /// /// 要删除的节点列表 public void RemoveNodes(IEnumerable nodesToRemove) { foreach (var node in nodesToRemove.ToList()) // 使用 ToList() 避免修改集合时的枚举错误 { RemoveNode(node); } } #endregion #region 序列化 public JObject JsonPrint(IEnumerable? nodes = null, int loop = 0) { // 如果传入的节点为空,使用默认的 Nodes 集合 if (nodes == null) nodes = Nodes; JObject resultObject = new JObject(); foreach (var node in nodes) { JObject nodeObject = new JObject(); // 为当前节点添加基本信息 nodeObject["Type"] = node.GetType().Name; nodeObject["Text"] = node.Text; // 添加文本内容 // 使用模式匹配简化类型检查 switch (node) { case CheckboxTreeNode checkboxNode: nodeObject["IsChecked"] = checkboxNode.obj.IsChecked?.ToString() ?? "false"; nodeObject["Tag"] = checkboxNode.obj.Tag?.ToString() ?? string.Empty; break; case ComboboxTreeNode comboboxNode: nodeObject["SelectedItem"] = comboboxNode.obj.SelectedItem?.ToString() ?? string.Empty; nodeObject["SelectedIndex"] = comboboxNode.obj.SelectedIndex; // 添加所有选项 var items = new JArray(); foreach (var item in comboboxNode.obj.Items) { items.Add(item.ToString()); } nodeObject["Items"] = items; break; case LabelTreeNode labelNode: nodeObject["Content"] = labelNode.obj.Content?.ToString() ?? string.Empty; break; } // 处理子节点 - 使用更合适的属性名 if (node.Children.Count > 0) { JObject childrenObject = JsonPrint(node.Children, loop + 1); nodeObject["Children"] = childrenObject; // 改为更合适的属性名 } // 使用唯一键名避免重复键问题 string key = node.Text; int counter = 1; while (resultObject.ContainsKey(key)) { key = $"{node.Text}_{counter}"; counter++; } resultObject.Add(key, nodeObject); } return resultObject; } public void JsonParse(string jsonContent) { // 清空现有数据 Clear(); if (string.IsNullOrWhiteSpace(jsonContent)) return; try { JObject rootObject = JObject.Parse(jsonContent); ParseNodes(rootObject, null); } catch (Exception ex) { // 处理解析异常,可以根据需要记录日志或抛出异常 Debug.WriteLine($"JSON解析失败: {ex.Message}"); throw new ArgumentException("无效的JSON格式", ex); } } private void ParseNodes(JObject jObject, TreeNode parent) { foreach (var property in jObject.Properties()) { JObject nodeObject = property.Value as JObject; if (nodeObject == null) continue; // 获取节点类型 string nodeType = nodeObject["Type"]?.ToString() ?? ""; string text = nodeObject["Text"]?.ToString() ?? ""; TreeNode newNode = null; // 根据类型创建相应的节点 switch (nodeType) { case nameof(LabelTreeNode): newNode = CreateLabelTreeNode(nodeObject, text); break; case nameof(CheckboxTreeNode): newNode = CreateCheckboxTreeNode(nodeObject, text); break; case nameof(ComboboxTreeNode): newNode = CreateComboboxTreeNode(nodeObject, text); break; default: break; } if (newNode != null) { // 添加到树中 if (parent == null) { Nodes.Add(newNode); } else { newNode.Parent = parent; parent.Children.Add(newNode); } // 递归处理子节点 if (nodeObject["Children"] is JObject childrenObject) { ParseNodes(childrenObject, newNode); } } } } private LabelTreeNode CreateLabelTreeNode(JObject nodeObject, string text) { var labelNode = new LabelTreeNode { Text = text, obj = new Label { Content = nodeObject["Content"]?.ToString() ?? text } }; return labelNode; } private CheckboxTreeNode CreateCheckboxTreeNode(JObject nodeObject, string text) { bool isChecked = bool.TryParse(nodeObject["IsChecked"]?.ToString(), out var result) && result; string tag = nodeObject["Tag"]?.ToString() ?? text; var checkboxNode = new CheckboxTreeNode { Text = text, obj = new CheckBox { Content = text, IsChecked = isChecked, Tag = tag, ToolTip = tag, Foreground = Brushes.White, VerticalAlignment = VerticalAlignment.Center } }; return checkboxNode; } private ComboboxTreeNode CreateComboboxTreeNode(JObject nodeObject, string text) { var comboboxNode = new ComboboxTreeNode { Text = text, obj = new ComboBox { VerticalAlignment = VerticalAlignment.Center, MinWidth = 100 } }; // 添加选项 if (nodeObject["Items"] is JArray itemsArray) { foreach (var item in itemsArray) { comboboxNode.obj.Items.Add(item.ToString()); } } // 设置选中项 int selectedIndex = nodeObject["SelectedIndex"]?.Value() ?? 0; if (selectedIndex >= 0 && selectedIndex < comboboxNode.obj.Items.Count) { comboboxNode.obj.SelectedIndex = selectedIndex; } return comboboxNode; } #endregion #region 动力学 public void Clear() { Nodes.Clear(); } public void ExpandAll(object? sender = null, RoutedEventArgs? e = null) { foreach (var node in Nodes) { ExpandNode(node); } } public void CollapseAll(object? sender=null, RoutedEventArgs? e=null) { foreach (var node in Nodes) { CollapseNode(node); } } public 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); } } public 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 #endregion #region 私有方法 public void AddNode(TreeNode node, TreeNode parent) { if (parent == null) { node.Parent = null; Nodes.Add(node); } else { node.Parent = parent; parent.Children.Add(node); } } private IEnumerable GetAllNodes(IEnumerable? nodes=null) { if (nodes == null) nodes = null; foreach (var node in nodes) { yield return node; foreach (var child in GetAllNodes(node.Children)) { yield return child; } } } #endregion } #region 数据模型 public abstract class TreeNode : INotifyPropertyChanged { private string _text; private ObservableCollection _children; private TreeNode _parent; #region 初始化结构 public event PropertyChangedEventHandler? PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public TreeNode() { _children = new ObservableCollection(); } #endregion public string Text { get => _text; set { if (_text != value) { _text = value; OnPropertyChanged(nameof(Text)); } } } public ObservableCollection Children { get => _children; set { if (_children != value) { _children = value; OnPropertyChanged(nameof(Children)); } } } public TreeNode Parent { get => _parent; set { if (_parent != value) { // 防止设置自己为自己的父节点 if (value == this) throw new InvalidOperationException("不能将节点设置为自己的父节点"); // 防止循环引用(检查祖先链) var current = value; while (current != null) { if (current == this) throw new InvalidOperationException("检测到循环引用"); current = current.Parent; } _parent = value; OnPropertyChanged(nameof(Parent)); } } } } public class LabelTreeNode : TreeNode { private Label _obj; public Label obj { get => _obj; set { if (_obj != value) { _obj = value; OnPropertyChanged(nameof(obj)); } } } } public class ComboboxTreeNode : TreeNode { private ComboBox _obj; public ComboBox obj { get => _obj; set { if (_obj != value) { _obj = value; OnPropertyChanged(nameof(obj)); } } } } public class CheckboxTreeNode : TreeNode { private CheckBox _obj; public CheckBox obj { get => _obj; set { if (_obj != value) { _obj = value; OnPropertyChanged(nameof(obj)); } } } } public class RadioButtonTreeNode : TreeNode { private RadioButton _obj; public RadioButton obj { get => _obj; set { if (_obj != value) { _obj = value; OnPropertyChanged(nameof(obj)); } } } } #endregion }