using 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 IsExpandedChange; public event EventHandler 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); } } /// /// 用于展开的可见 /// /// private void SetItemsVisible(bool visible) { if (IsExpanded == false || visible == false) { Items.ForEach(p => p.IsVisible = false); } else { Items.ForEach(p => p.IsVisible = true); } } /// /// 设置筛选是否可见,比如筛选name1,则包含name1的数据和其父节点都可见 /// public bool SelectVisible { get { return _IsVisible; } set { if (_IsVisible == value) { return; } _IsVisible = value; Set("IsVisible"); SetItemsVisible(value); } } /// /// 用于筛选的可见 /// /// 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 /// /// 所有子项数量 /// 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 _ParentItems = null; public List ParentItems { get { if (_ParentItems == null) { _ParentItems = new List(); } return _ParentItems; } set { _ParentItems = value; Set("ParentItems"); } } #endregion #region 属性 Items private List _Items = null; public List Items { get { if (_Items == null) { _Items = new List(); } return _Items; } set { _Items = value; Set("Items"); } } #endregion #region 属性 HasItems public bool HasItems { get { return Items.Count > 0; } } #endregion #region 属性 IconType /// /// 他是控制树前的按钮的,有事找他 /// 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 { IEnumerable _SourceItems = null; string _ItemsPath = ""; List _RootItems = new List(); List levelOneItems = new List(); private PropertyInfo subDataProperty; #region 属性 UseTree private bool _UseTree = true; public bool UseTree { get { return _UseTree; } set { _UseTree = value; } } public List 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(); _RootItems.Clear(); Dictionary 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 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 GetSubItems(TreeItemData treeItem, string itemsPath, Dictionary 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; } } }