CPF/CPF/UIElementCollection.cs
2023-12-27 15:24:48 +08:00

596 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Linq;
namespace CPF
{
/// <summary>
/// 子元素集合
/// </summary>
public class UIElementCollection : IEnumerable<UIElement>, IList, IList<UIElement>
#if NET40
#else
, IReadOnlyList<UIElement>
#endif
{
UIElement owner;
public UIElementCollection(UIElement owner)
{
this.owner = owner;
orderByZIndexList = ElementList;
}
List<UIElement> UIElements = new List<UIElement>();
/// <summary>
/// 内部UIElementList
/// </summary>
public List<UIElement> ElementList
{
get { return UIElements; }
}
UIElement[] list;
/// <summary>
/// 获取根据TabIndex排序之后的List
/// </summary>
internal UIElement[] OrderByTabIndexList()
{
//get
//{
if (list == null)
{
list = UIElements.ToArray();
SortOfTabIndex(list);
}
return list;
//}
}
private static void SortOfTabIndex(UIElement[] list)
{//选择排序
int min;
for (int i = 0; i < list.Length; i++)
{
min = i;
for (int j = i + 1; j < list.Length; j++)
{
if (list[j].TabIndex - list[min].TabIndex < 0)
{
min = j;
}
}
UIElement temp = list[i];
list[i] = list[min];
list[min] = temp;
}
}
IList<UIElement> orderByZIndexList;
/// <summary>
/// 获取根据ZIndex排序之后的List
/// </summary>
internal IList<UIElement> OrderByZIndexList()
{
//get
//{
if (orderByZIndexList == null)
{
SortOfZIndex();
}
return orderByZIndexList;
//}
}
/// <summary>
/// 相同的值如果出现不相同将为int.Min
/// </summary>
int zindex = 0;
/// <summary>
/// 根据ZIndex属性排序
/// </summary>
void SortOfZIndex()
{//选择排序
if (UIElements.Count < 2)
{
orderByZIndexList = UIElements;
return;
}
orderByZIndexList = UIElements.ToList();
int min;
for (int i = 0; i < orderByZIndexList.Count; i++)
{
min = i;
for (int j = i + 1; j < orderByZIndexList.Count; j++)
{
if (orderByZIndexList[j].ZIndex - orderByZIndexList[min].ZIndex < 0)
{
min = j;
}
}
UIElement temp = orderByZIndexList[i];
orderByZIndexList[i] = orderByZIndexList[min];
orderByZIndexList[min] = temp;
}
zindex = orderByZIndexList[0].ZIndex;
for (int i = 1; i < orderByZIndexList.Count; i++)
{
if (zindex != orderByZIndexList[i].ZIndex)
{
zindex = int.MinValue;
break;
}
}
}
/// <summary>
/// 重新按照ZIndex排序
/// </summary>
internal void InvalidateZIndex()
{
orderByZIndexList = null;
}
void AddUpdateZindex(UIElement element)
{
if (UIElements.Count == 1)
{
zindex = element.ZIndex;
}
else if (UIElements.Count > 1 && zindex != element.ZIndex)
{
zindex = int.MinValue;
InvalidateZIndex();
}
}
void RemoveUpdateZindex(UIElement element)
{
if (UIElements.Count == 1)
{
zindex = ElementList[0].ZIndex;
if (orderByZIndexList != null && orderByZIndexList != ElementList)
{
orderByZIndexList.Remove(element);
}
}
else if (ElementList.Count > 1)
{
if (orderByZIndexList != null && orderByZIndexList != ElementList)
{
orderByZIndexList.Remove(element);
}
}
else
{
orderByZIndexList = UIElements;
}
}
public T Add<T>(T visual) where T : UIElement
{
if (visual == null)
{ return null; }
if (visual.Parent != null)
{
visual.Parent.Children.Remove(visual);
}
visual.Parent = owner;
UIElements.Add(visual);
list = null;
AddUpdateZindex(visual);
owner.RaiseUIElementAdded(visual);
return visual;
}
void ICollection<UIElement>.Add(UIElement visual)
{
Add(visual);
}
public void Add(IEnumerable<UIElement> items)
{
if (items == null)
{
return;
}
UIElements.AddRange(items);
foreach (UIElement item in items)
{
if (item.Parent != null)
{
item.Parent.Children.Remove(item);
}
item.Parent = owner;
list = null;
AddUpdateZindex(item);
owner.RaiseUIElementAdded(item);
}
}
public void Clear()
{
UIElement[] v = UIElements.ToArray();
UIElements.Clear();
list = null;
foreach (UIElement item in v)
{
item.Parent = null;
owner.RaiseUIElementRemoved(item);
}
orderByZIndexList = UIElements;
}
public bool Contains(UIElement value)
{
return UIElements.Contains(value);
}
public int IndexOf(UIElement value)
{
return UIElements.IndexOf(value);
}
/// <summary>
/// 将控件插入到指定索引处
/// </summary>
/// <param name="index"></param>
/// <param name="visual"></param>
public void Insert(int index, UIElement visual)
{
//if (!controls.Contains(visual))
//{
UIElement parent = visual.Parent as UIElement;
if (parent != null)//如果原来已经添加在其他控件集合里
{
parent.Children.Remove(visual);//移出控件
}
UIElements.Insert(index, visual);
visual.Parent = owner;
list = null;
AddUpdateZindex(visual);
owner.RaiseUIElementAdded(visual);
//}
}
bool IList.Contains(object value)
{
return UIElements.Contains((UIElement)value);
}
int IList.IndexOf(object value)
{
return UIElements.IndexOf((UIElement)value);
}
void IList.Insert(int index, object value)
{
UIElement visual = value as UIElement;
if (visual != null)
{
Insert(index, visual);
}
}
int IList.Add(object value)
{
UIElement v = value as UIElement;
if (v != null)
{
Add(v);
return UIElements.Count - 1;
}
return -1;
}
bool IList.IsFixedSize
{
get { return false; }
}
bool IList.IsReadOnly
{
get { return false; }
}
void IList.Remove(object value)
{
UIElement v = value as UIElement;
if (v != null)
{
Remove(v);
}
}
object IList.this[int index]
{
get
{
return UIElements[index];
}
set
{
throw new NotImplementedException();
}
}
bool ICollection.IsSynchronized
{
get { return true; }
}
object ICollection.SyncRoot
{
get { return this; }
}
public UIElement this[int index]
{
get { return UIElements[index]; }
set
{
if (value == null)
{
throw new Exception("UIElement不能为空");
}
var old = UIElements[index];
if (old == value)
{
return;
}
if (value.Parent != null)
{
value.Parent.Children.Remove(value);
}
old.Parent = null;
list = null;
RemoveUpdateZindex(old);
owner.RaiseUIElementRemoved(old);
value.Parent = owner;
UIElements[index] = value;
list = null;
AddUpdateZindex(value);
owner.RaiseUIElementAdded(value);
}
}
public UIElement this[string name]
{
get
{
foreach (UIElement item in UIElements)
{
if (item.Name == name)
{
return item;
}
}
return null;
}
}
public void Remove(UIElement value)
{
if (value == null || UIElements.Count == 0)
{
return;
}
UIElements.Remove(value);
value.Parent = null;
list = null;
RemoveUpdateZindex(value);
owner.RaiseUIElementRemoved(value);
}
public void RemoveAt(int index)
{
UIElement visual = UIElements[index];
UIElements.RemoveAt(index);
visual.Parent = null;
list = null;
RemoveUpdateZindex(visual);
owner.RaiseUIElementRemoved(visual);
}
public void RemoveRange(int start, int count)
{
UIElement[] vs = new UIElement[count];
int index = 0;
for (int i = start; i < start + count; i++)
{
vs[index] = UIElements[i];
index++;
}
UIElements.RemoveRange(start, count);
list = null;
foreach (UIElement item in vs)
{
item.Parent = null;
RemoveUpdateZindex(item);
owner.RaiseUIElementRemoved(item);
}
}
public void CopyTo(Array array, int index)
{
if (array != null && array.Length > 0)
{
UIElements.CopyTo((UIElement[])array, index);
}
}
public int Count
{
get { return UIElements.Count; }
}
public bool IsReadOnly
{
get
{
return false;
}
}
public UIElement Owner
{
get
{
return owner;
}
}
UIElement IList<UIElement>.this[int index]
{
get
{
return UIElements[index];
}
set
{
throw new NotImplementedException();
}
}
/// <summary>
/// 使用指定的比较器对所有元素进行排序
/// </summary>
/// <param name="comparer">比较元素时要使用的比较器</param>
public void Sort(Comparer<UIElement> comparer)
{
UIElements.Sort(comparer);
}
/// <summary>
/// 使用指定的比较器对所有元素进行排序。
/// </summary>
/// <param name="comparer">比较元素时要使用的比较器</param>
public void Sort(IComparer<UIElement> comparer)
{
UIElements.Sort(comparer);
}
/// <summary>
/// 使用指定的 System.Comparison 对整个 UIElementCollection 中的元素进行排序。
/// </summary>
/// <param name="comparison"></param>
public void Sort(Comparison<UIElement> comparison)
{
UIElements.Sort(comparison);
}
/// <summary>
/// 使用指定的比较器对某个范围内的元素进行排序。
/// </summary>
/// <param name="index">要排序的范围的从零开始的起始索引。</param>
/// <param name="count">要排序的范围的长度</param>
/// <param name="comparer">比较元素时要使用的比较器</param>
public void Sort(int index, int count, IComparer<UIElement> comparer)
{
UIElements.Sort(index, count, comparer);
}
/// <summary>
/// 搜索与指定谓词所定义的条件相匹配的元素,并返回整个集合中的第一个匹配元素
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public UIElement Find(Predicate<UIElement> match)
{
return UIElements.Find(match);
}
/// <summary>
/// 确定 集合 是否包含与指定谓词所定义的条件相匹配的元素
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public bool Exists(Predicate<UIElement> match)
{
return UIElements.Exists(match);
}
/// <summary>
/// 检索与指定谓词定义的条件匹配的所有元素
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public List<UIElement> FindAll(Predicate<UIElement> match)
{
return UIElements.FindAll(match);
}
/// <summary>
/// 搜索与指定谓词所定义的条件相匹配的元素,并返回整个集合 中第一个匹配元素的从零开始的索引。
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public int FindIndex(Predicate<UIElement> match)
{
return UIElements.FindIndex(match);
}
/// <summary>
/// 搜索与指定谓词所定义的条件相匹配的元素,并返回整个 集合 中的最后一个匹配元素。
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public UIElement FindLast(Predicate<UIElement> match)
{
return UIElements.FindLast(match);
}
/// <summary>
/// 搜索与指定谓词所定义的条件相匹配的元素,并返回整个 集合 中最后一个匹配元素的从零开始的索引。
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public int FindLastIndex(Predicate<UIElement> match)
{
return UIElements.FindLastIndex(match);
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)UIElements).GetEnumerator();
}
public IEnumerator<UIElement> GetEnumerator()
{
return UIElements.GetEnumerator();
}
public void CopyTo(UIElement[] array, int arrayIndex)
{
UIElements.CopyTo(array, arrayIndex);
}
/// <summary>
/// 释放并清空子元素
/// </summary>
internal void DisposeChildren()
{
var count = UIElements.Count;
for (int i = 0; i < count; i++)
{
//UIElements[count - i - 1].Dispose();
var item = UIElements[count - i - 1];
if (item is Controls.ContentControl c)
{
c.Content = null;
}
item.DataContext = null;
item.Dispose();
}
}
bool ICollection<UIElement>.Remove(UIElement item)
{
var r = item.Parent == owner;
Remove(item);
return r;
}
public override string ToString()
{
return Count.ToString();
}
}
}