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.

252 lines
9.0 KiB
C#

1 month ago
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)
{
1 month ago
// 1. 动态逻辑必须禁用缓存,否则状态切换无法实时生效
// Type typeObj = value.GetType();
// if (GlobalPropertyDescriptor.TryGetValue(typeObj, out PropertyDescriptorCollection properties))
// {
// return properties;
// }
// 2. 获取原始属性
PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(value, attributes);
// 3. 动态获取当前对象的 RulerDataStyle 值(使用反射避免命名空间引用错误)
int currentStyle = -1;
var styleProp = pdc["RulerDataStyle"];
if (styleProp != null)
1 month ago
{
1 month ago
var val = styleProp.GetValue(value);
if (val != null) currentStyle = Convert.ToInt32(val);
1 month ago
}
// 原始属性
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);
}
}
}
1 month ago
1 month ago
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];
}
}
}
1 month ago
// 重新构建属性特性
var attrList = new List<Attribute>();
foreach (Attribute attr in pd.Attributes)
1 month ago
{
1 month ago
if (attr is CategoryAttribute)
1 month ago
{
1 month ago
attrList.Add(new CategoryAttribute(strCagegory));
1 month ago
}
1 month ago
else
{
attrList.Add(attr);
}
}
// 逻辑:如果当前属性是 RulerNumber且检测到的 Style 为 1 或 2 动态设置 RulerNumber 为只读
if (pd.Name == "RulerNumber" && (currentStyle == 1 || currentStyle == 2))
{
attrList.RemoveAll(a => a is ReadOnlyAttribute);
attrList.Add(new ReadOnlyAttribute(true));
1 month ago
}
1 month ago
// --------------------------------------------
1 month ago
1 month ago
finalList.Add(TypeDescriptor.CreateProperty(pd.ComponentType, pd, attrList.ToArray()));
1 month ago
}
// 重新设置类别属性
orderedProperties.Sort();
int nPropertyCount = orderedProperties.Count;
string[] saOrderNames = new string[nPropertyCount];
for (int i = 0; i < nPropertyCount; i++)
{
saOrderNames[i] = orderedProperties[i].Name;
}
1 month ago
1 month ago
PropertyDescriptorCollection result = new PropertyDescriptorCollection(finalList.ToArray(), true).Sort(saOrderNames);
1 month ago
// 返回结果(不存入 GlobalPropertyDescriptor
1 month ago
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
}