You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
8.1 KiB
C#
233 lines
8.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace SigmaDrawerStyle
|
|
{
|
|
/// <summary>
|
|
/// 属性排序类
|
|
/// </summary>
|
|
/// <seealso cref="System.ComponentModel.ExpandableObjectConverter" />
|
|
public class PropertySorter : ExpandableObjectConverter
|
|
{
|
|
#region Methods
|
|
/// <inheritdoc/>
|
|
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
|
|
{
|
|
return true;
|
|
}
|
|
public static Dictionary<Type, PropertyDescriptorCollection> GlobalPropertyDescriptor = new Dictionary<Type, PropertyDescriptorCollection>();
|
|
/// <inheritdoc/>
|
|
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
|
|
{
|
|
Type typeObj = value.GetType();
|
|
if (GlobalPropertyDescriptor.TryGetValue(typeObj, out PropertyDescriptorCollection properties))
|
|
{
|
|
return properties;
|
|
}
|
|
// 原始属性
|
|
PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(value, attributes);
|
|
List<PropertyOrderPair> orderedProperties = new List<PropertyOrderPair>();
|
|
|
|
List<string> lstOriginCategory = new List<string>();
|
|
List<string> lstCategoryTab = new List<string>();
|
|
List<string> lstCategoryNoTab = new List<string>();
|
|
|
|
foreach (PropertyDescriptor pd in pdc)
|
|
{
|
|
Attribute attribute = pd.Attributes[typeof(PropertyOrderAttribute)];
|
|
string strCategory = pd.Category;
|
|
if (attribute != null)
|
|
{
|
|
PropertyOrderAttribute poa = (PropertyOrderAttribute)attribute;
|
|
orderedProperties.Add(new PropertyOrderPair(pd.Name, poa.Order, strCategory));
|
|
}
|
|
else
|
|
{
|
|
// 没有序号的设置序号为 0
|
|
orderedProperties.Add(new PropertyOrderPair(pd.Name, 0, strCategory));
|
|
}
|
|
|
|
if (!lstOriginCategory.Contains(strCategory))
|
|
{
|
|
lstOriginCategory.Add(strCategory);
|
|
if (strCategory.IndexOf('\t') >= 0)
|
|
{
|
|
lstCategoryTab.Add(strCategory);
|
|
}
|
|
else
|
|
{
|
|
lstCategoryNoTab.Add(strCategory);
|
|
}
|
|
}
|
|
}
|
|
List<string> lstCategoryTabFinal = new List<string>();
|
|
List<string> lstCategoryNoTabFinal = new List<string>();
|
|
if (lstCategoryNoTab.Count > 1)
|
|
{
|
|
//char chNull = (char)0x0009;
|
|
char chNull = '\u200B';
|
|
lstCategoryTab.Sort();
|
|
for (int i = 0; i < lstCategoryTab.Count; i++)
|
|
{
|
|
string strCategory = lstCategoryTab[i];
|
|
strCategory = strCategory.Trim('\t');
|
|
|
|
strCategory = strCategory.PadLeft(strCategory.Length + lstOriginCategory.Count - i - 1, chNull);
|
|
lstCategoryTabFinal.Add(strCategory);
|
|
}
|
|
for (int i = 0; i < lstCategoryNoTab.Count; i++)
|
|
{
|
|
string strCategory = lstCategoryNoTab[i];
|
|
strCategory = strCategory.PadLeft(strCategory.Length + lstOriginCategory.Count - lstCategoryTab.Count - i - 1, chNull);
|
|
lstCategoryNoTabFinal.Add(strCategory);
|
|
}
|
|
}
|
|
|
|
List<PropertyDescriptor> finalList = new List<PropertyDescriptor>();
|
|
foreach (PropertyDescriptor pd in pdc)
|
|
{
|
|
string strCagegory = pd.Category;
|
|
if (lstCategoryNoTab.Count > 1)
|
|
{
|
|
int nIndex = lstCategoryTab.IndexOf(strCagegory);
|
|
if (nIndex >= 0)
|
|
{
|
|
strCagegory = lstCategoryTabFinal[nIndex];
|
|
}
|
|
else
|
|
{
|
|
nIndex = lstCategoryNoTab.IndexOf(strCagegory);
|
|
if (nIndex >= 0)
|
|
{
|
|
strCagegory = lstCategoryNoTabFinal[nIndex];
|
|
}
|
|
}
|
|
}
|
|
|
|
var attrs = new Attribute[pd.Attributes.Count];
|
|
pd.Attributes.CopyTo(attrs, 0);
|
|
|
|
// 更新CategoryAttribute
|
|
for (int j = 0; j < attrs.Length; j++)
|
|
{
|
|
if (attrs[j] is CategoryAttribute)
|
|
{
|
|
attrs[j] = new CategoryAttribute(strCagegory);
|
|
break;
|
|
}
|
|
}
|
|
|
|
finalList.Add(TypeDescriptor.CreateProperty(
|
|
pd.ComponentType,
|
|
pd,
|
|
attrs));
|
|
}
|
|
|
|
// 重新设置类别属性
|
|
orderedProperties.Sort();
|
|
int nPropertyCount = orderedProperties.Count;
|
|
string[] saOrderNames = new string[nPropertyCount];
|
|
for (int i = 0; i < nPropertyCount; i++)
|
|
{
|
|
saOrderNames[i] = orderedProperties[i].Name;
|
|
}
|
|
PropertyDescriptorCollection result = new PropertyDescriptorCollection(finalList.ToArray(), true).Sort(saOrderNames);
|
|
GlobalPropertyDescriptor.Add(typeObj, result);
|
|
return result;
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
#region Helper Class - PropertyOrderAttribute
|
|
[AttributeUsage(AttributeTargets.Property)]
|
|
public class PropertyOrderAttribute : Attribute
|
|
{
|
|
//
|
|
// Simple attribute to allow the order of a property to be specified
|
|
//
|
|
private int _order;
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="PropertyOrderAttribute"/> class.
|
|
/// </summary>
|
|
/// <param name="order"></param>
|
|
public PropertyOrderAttribute(int order)
|
|
{
|
|
_order = order;
|
|
}
|
|
|
|
public int Order
|
|
{
|
|
get
|
|
{
|
|
return _order;
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Helper Class - PropertyOrderPair
|
|
public class PropertyOrderPair : IComparable
|
|
{
|
|
private int _order;
|
|
private string _name;
|
|
public string Category { get; set; }
|
|
public string Name
|
|
{
|
|
get
|
|
{
|
|
return _name;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="PropertyOrderPair"/> class.
|
|
/// </summary>
|
|
/// <param name="name">名称</param>
|
|
/// <param name="order">顺序号</param>
|
|
public PropertyOrderPair(string name, int order)
|
|
{
|
|
_order = order;
|
|
_name = name;
|
|
}
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="PropertyOrderPair"/> class.
|
|
/// </summary>
|
|
/// <param name="name">名称.</param>
|
|
/// <param name="order">序号.</param>
|
|
/// <param name="category">分类.</param>
|
|
public PropertyOrderPair(string name, int order, string category)
|
|
: this(name, order)
|
|
{
|
|
this.Category = category;
|
|
}
|
|
|
|
public int CompareTo(object obj)
|
|
{
|
|
//
|
|
// Sort the pair objects by ordering by order value
|
|
// Equal values get the same rank
|
|
//
|
|
int otherOrder = ((PropertyOrderPair)obj)._order;
|
|
if (otherOrder == _order)
|
|
{
|
|
//
|
|
// If order not specified, sort by name
|
|
//
|
|
string otherName = ((PropertyOrderPair)obj)._name;
|
|
return string.Compare(_name, otherName);
|
|
}
|
|
else if (otherOrder > _order)
|
|
{
|
|
return -1;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
#endregion
|
|
}
|