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<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>
|
/// 设置筛选是否可见,比如筛选name1,则包含name1的数据和其父节点都可见
|
/// </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;
|
}
|
}
|
}
|