From 9d1660270272180cd71147d6ddd53d1382643d2e Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期一, 02 十一月 2026 18:00:14 +0800
Subject: [PATCH] merge: 并入远程 Initial commit 作为历史根节点

---
 HMI.UI/Controls/treegrid/Controls/TreeItemData.cs |  587 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 587 insertions(+), 0 deletions(-)

diff --git a/HMI.UI/Controls/treegrid/Controls/TreeItemData.cs b/HMI.UI/Controls/treegrid/Controls/TreeItemData.cs
new file mode 100644
index 0000000..c49c447
--- /dev/null
+++ b/HMI.UI/Controls/treegrid/Controls/TreeItemData.cs
@@ -0,0 +1,587 @@
+锘縰sing HMI.Core.Entity;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Windows.Data;
+
+namespace HMI.UI
+{
+    public class TreeItemData : NotifyBase
+    {
+
+        public event EventHandler<bool> IsExpandedChange;
+        public event EventHandler<bool> VisibleChange;
+
+        protected override void Set(string name)
+        {
+            base.Set(name);
+            if (!name.Equals("IconType"))
+            {
+                IconType = GetIconType();
+            }
+        }
+
+        #region 灞炴�� IsExpanded
+        private bool _IsExpanded = true;
+        public bool IsExpanded
+        {
+            get => _IsExpanded;
+            set
+            {
+                //if (_IsExpanded == value)
+                //{
+                //    return;
+                //}
+                _IsExpanded = value;
+                Set("IsExpanded");
+                SetItemsVisible(value);
+                IsExpandedChange?.Invoke(this, value);
+            }
+        }
+        #endregion
+
+        #region 灞炴�� IsVisible
+        private bool _IsVisible = true;
+
+        public bool IsVisible
+        {
+            get
+            {
+                return _IsVisible;
+            }
+            set
+            {
+                if (_IsVisible == value)
+                {
+                    return;
+                }
+                _IsVisible = value;
+                Set("IsVisible");
+                SetItemsVisible(value);
+                VisibleChange?.Invoke(this, value);
+            }
+        }
+
+        /// <summary>
+        /// 鐢ㄤ簬灞曞紑鐨勫彲瑙�
+        /// </summary>
+        /// <param name="visible"></param>
+        private void SetItemsVisible(bool visible)
+        {
+            if (IsExpanded == false || visible == false)
+            {
+                Items.ForEach(p => p.IsVisible = false);
+            }
+            else
+            {
+                Items.ForEach(p => p.IsVisible = true);
+            }
+        }
+
+        /// <summary>
+        /// 璁剧疆绛涢�夋槸鍚﹀彲瑙侊紝姣斿绛涢�塶ame1,鍒欏寘鍚玭ame1鐨勬暟鎹拰鍏剁埗鑺傜偣閮藉彲瑙�
+        /// </summary>
+        public bool SelectVisible
+        {
+            get
+            {
+                return _IsVisible;
+            }
+            set
+            {
+                if (_IsVisible == value)
+                {
+                    return;
+                }
+                _IsVisible = value;
+                Set("IsVisible");
+                SetItemsVisible(value);
+            }
+        }
+
+        /// <summary>
+        /// 鐢ㄤ簬绛涢�夌殑鍙
+        /// </summary>
+        /// <param name="visible"></param>
+        private void SetSelectVisible(bool visible)
+        {
+            if (visible)
+            {
+                ParentItem.SelectVisible = visible;
+            }
+            Items.ForEach(p => p.IsVisible = visible);
+        }
+        #endregion
+
+        public void NotifyUI()
+        {
+            IsExpanded = _IsExpanded;
+        }
+
+        #region 灞炴�� Level
+        private int _Level = 0;
+        public int Level
+        {
+            get
+            {
+                return _Level;
+            }
+            set
+            {
+                _Level = value;
+                Set("Level");
+            }
+        }
+        #endregion
+
+        #region 灞炴�� IsFirstItem
+        private bool _IsFirstItem = true;
+        public bool IsFirstItem
+        {
+            get
+            {
+                return _IsFirstItem;
+            }
+            set
+            {
+                _IsFirstItem = value;
+                Set("IsFirstItem");
+            }
+        }
+        #endregion
+
+        #region 灞炴�� IsLastItem
+        private bool _IsLastItem = false;
+        public bool IsLastItem
+        {
+            get
+            {
+                return _IsLastItem;
+            }
+            set
+            {
+                _IsLastItem = value;
+                Set("IsLastItem");
+            }
+        }
+        #endregion
+
+        #region 灞炴�� Data
+        private object _Data = null;
+        public object Data
+        {
+            get
+            {
+                return _Data;
+            }
+            set
+            {
+                _Data = value;
+                Set("Data");
+            }
+        }
+        #endregion
+
+        /// <summary>
+        /// 鎵�鏈夊瓙椤规暟閲�
+        /// </summary>
+        private int allSubCount;
+
+        public int AllSubCount
+        {
+            get { return allSubCount; }
+            set { allSubCount = value; }
+        }
+
+
+        #region 灞炴�� ParentItem
+        private TreeItemData _ParentItem = null;
+        public TreeItemData ParentItem
+        {
+            get
+            {
+                return _ParentItem;
+            }
+            set
+            {
+                _ParentItem = value;
+                Set("ParentItem");
+            }
+        }
+        #endregion
+
+        #region 灞炴�� ParentItems
+        private List<TreeItemData> _ParentItems = null;
+        public List<TreeItemData> ParentItems
+        {
+            get
+            {
+                if (_ParentItems == null)
+                {
+                    _ParentItems = new List<TreeItemData>();
+                }
+                return _ParentItems;
+            }
+            set
+            {
+                _ParentItems = value;
+                Set("ParentItems");
+            }
+        }
+        #endregion
+
+        #region 灞炴�� Items
+        private List<TreeItemData> _Items = null;
+        public List<TreeItemData> Items
+        {
+            get
+            {
+                if (_Items == null)
+                {
+                    _Items = new List<TreeItemData>();
+                }
+                return _Items;
+            }
+            set
+            {
+                _Items = value;
+                Set("Items");
+            }
+        }
+        #endregion
+
+        #region 灞炴�� HasItems
+        public bool HasItems
+        {
+            get
+            {
+                return Items.Count > 0;
+            }
+        }
+        #endregion
+
+        #region 灞炴�� IconType
+        /// <summary>
+        /// 浠栨槸鎺у埗鏍戝墠鐨勬寜閽殑锛屾湁浜嬫壘浠�
+        /// </summary>
+        private int _IconType = 0;
+        public int IconType
+        {
+            get
+            {
+                return _IconType;
+            }
+            set
+            {
+                if (_IconType == value)
+                {
+                    return;
+                }
+
+                _IconType = value;
+                Set("IconType");
+            }
+        }
+        #endregion
+
+        int GetIconType()
+        {
+            if (HasItems)
+            {
+                if (IsFirstItem && IsLastItem && Level == 0)
+                {
+                    return IsExpanded ? 5 : 1;
+                }
+
+                if (Level == 0 && IsFirstItem)
+                {
+                    return IsExpanded ? 5 : 2;
+                }
+
+                if (IsLastItem)
+                {
+                    return IsExpanded ? 7 : 0;
+                }
+
+                return IsExpanded ? 7 : 0;
+            }
+            if (IsLastItem)
+            {
+                return 9;
+            }
+            else
+            {
+                return 8;
+            }
+        }
+    }
+
+    public class TreeItemDataCollection : ObservableCollection<TreeItemData>
+    {
+        IEnumerable _SourceItems = null;
+
+        string _ItemsPath = "";
+
+        List<TreeItemData> _RootItems = new List<TreeItemData>();
+        List<TreeItemData> levelOneItems = new List<TreeItemData>();
+
+        private PropertyInfo subDataProperty;
+
+        #region 灞炴�� UseTree
+        private bool _UseTree = true;
+        public bool UseTree
+        {
+            get
+            {
+                return _UseTree;
+            }
+            set
+            {
+                _UseTree = value;
+            }
+        }
+
+        public List<TreeItemData> RootItems
+        {
+            get => _RootItems;
+        }
+
+        #endregion
+
+        public TreeItemDataCollection()
+        {
+
+        }
+
+        public TreeItemDataCollection(IEnumerable sourceItems, string itemsPath, bool useTree = false)
+        {
+            _SourceItems = sourceItems;
+            _ItemsPath = itemsPath;
+            if (_SourceItems is INotifyCollectionChanged list)
+            {
+                list.CollectionChanged += List_CollectionChanged;
+            }
+            UseTree = useTree;
+            ResetItems();
+            //subDataProperty = typeof(T).GetProperty(itemsPath);
+        }
+
+        protected override void MoveItem(int oldIndex, int newIndex)
+        {
+            CheckReentrancy();
+            TreeItemData source = base[oldIndex];
+            TreeItemData target = base[newIndex];
+            newIndex += target.AllSubCount;
+            if (newIndex == oldIndex - 1)
+            {
+                return;
+            }
+            target = base[newIndex];
+            int times = source.AllSubCount;
+
+            if (oldIndex < newIndex)
+            {
+                base.RemoveItem(oldIndex);
+                base.InsertItem(newIndex, source);
+                OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
+                /// 浠庝笂寰�涓嬫媺
+                for (int i = 0; i < times; i++)
+                {
+                    CheckReentrancy();
+                    source = base[oldIndex];
+                    target = base[newIndex];
+                    base.RemoveItem(oldIndex);
+                    base.InsertItem(newIndex, source);
+                    OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
+                }
+            }
+            else if (oldIndex > newIndex)
+            {
+                /// 浠庝笅寰�涓婃媺
+                base.RemoveItem(oldIndex);
+                base.InsertItem(++newIndex, source);
+                OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
+                //MessageBox.Show($"source: {source.Data} {oldIndex}; target: {target.Data} {newIndex}");
+                for (int i = 0; i < times; i++)
+                {
+                    oldIndex++;
+                    newIndex++;
+                    CheckReentrancy();
+                    source = base[oldIndex];
+                    target = base[newIndex];
+                    //MessageBox.Show($"source: {source.Data} {oldIndex}; target: {target.Data} {newIndex}");
+                    base.RemoveItem(oldIndex);
+                    base.InsertItem(newIndex, source);
+                    OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
+                }
+            }
+        }
+
+        private void List_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+        {
+            //ResetItems();
+        }
+
+        public void ResetItems()
+        {
+            CheckReentrancy();
+            if (_SourceItems is null)
+            {
+                ClearAllItems();
+                return;
+            }
+
+            var items = new List<TreeItemData>();
+            _RootItems.Clear();
+
+            Dictionary<dynamic, TreeItemData> list = this.Items.
+                ToLookup(t => t.Data, t => t).ToDictionary(t => t.Key, t => t.First());
+            foreach (var item in _SourceItems)
+            {
+                if (list.TryGetValue(item, out var treeItem))
+                {
+                    list.Remove(item);
+                }
+                else
+                {
+                    treeItem = new TreeItemData { Data = item };
+                }
+
+                treeItem.ParentItems.Clear();
+                treeItem.Level = 0;
+                items.Add(treeItem);
+                _RootItems.Add(treeItem);
+                var subItems = GetSubItems(treeItem, _ItemsPath, list);
+                treeItem.AllSubCount = subItems.Count();
+                foreach (var sitem in subItems)
+                {
+                    items.Add(sitem);
+                }
+            }
+
+            ResetSubItems(_RootItems);
+
+            this.Items.Clear();
+            items.ForEach(t => this.Items.Add(t));
+            //if (UseTree)
+            //{
+            //    _RootItems.ForEach(t => this.Items.Add(t));
+            //}
+            //else
+            //{
+            //    items.ForEach(t => this.Items.Add(t));
+            //}
+            OnPropertyChanged(new PropertyChangedEventArgs("Count"));
+            OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
+        }
+
+        public static void ResetSubItems(IList<TreeItemData> items)
+        {
+            for (int i = 0; i < items.Count; i++)
+            {
+                var item = items[i];
+                item.IsFirstItem = i == 0;
+                item.IsLastItem = i == items.Count - 1;
+            }
+        }
+
+        private IEnumerable<TreeItemData> GetSubItems(TreeItemData treeItem, string itemsPath, Dictionary<object, TreeItemData> list)
+        {
+            var data = treeItem.Data;
+            var p = data.GetType().GetProperty(itemsPath);
+            var pvalue = p.GetValue(data, null);
+
+            if (pvalue is INotifyCollectionChanged inc)
+            {
+                //inc.CollectionChanged -= List_CollectionChanged;
+                //inc.CollectionChanged += List_CollectionChanged;
+            }
+
+            treeItem.Items.Clear();
+            if (pvalue is IEnumerable subItems)
+            {
+                foreach (var item in subItems)
+                {
+                    if (list.TryGetValue(item, out var subitem))
+                    {
+                        list.Remove(item);
+                    }
+                    else
+                    {
+                        subitem = new TreeItemData { Data = item };
+                    }
+
+                    subitem.ParentItem = treeItem;
+                    subitem.Level = treeItem.Level + 1;
+
+                    subitem.ParentItems.Clear();
+                    foreach (var pitem in treeItem.ParentItems)
+                    {
+                        subitem.ParentItems.Add(pitem);
+                    }
+                    subitem.ParentItems.Add(treeItem);
+
+                    treeItem.Items.Add(subitem);
+                    yield return subitem;
+                    var subSub = GetSubItems(subitem, itemsPath, list);
+                    subitem.AllSubCount = subSub.Count();
+                    foreach (var sitem in subSub)
+                    {
+                        yield return sitem;
+                    }
+                }
+                if (treeItem.Items.Count > 0)
+                {
+                    ResetSubItems(treeItem.Items);
+                }
+            }
+        }
+
+        private void ClearAllItems()
+        {
+            this.Items.Clear();
+        }
+    }
+
+    public class TreeItemDataConverter : IValueConverter
+    {
+        #region 灞炴�� UseTree
+        private bool _UseTree = false;
+        public bool UseTree
+        {
+            get
+            {
+                return _UseTree;
+            }
+            set
+            {
+                _UseTree = value;
+            }
+        }
+        #endregion
+
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value == null || parameter == null)
+            {
+                return value;
+            }
+            if (value is IEnumerable items)
+            {
+                return new TreeItemDataCollection(items, parameter.ToString(), UseTree);
+            }
+            return value;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            return value;
+        }
+    }
+}

--
Gitblit v1.9.1