目录
一、 导入数据
二、 PropertyGrid 的简单属性配置
三、 设置字段属性
四、 字段的下拉框
五、 多级展开
六、 显示内容的排序
6.1 属性排序
6.1.1 自定义排序
6.1.2 根据字段封装顺序SEO靠我
6.2 类别排序
七、 闪屏问题
八、 主要参考
一、 导入数据
propertyGrid1.SelectedObject = new Level1();
显示Level1类中所有 public 属性 Get
SEO靠我Set 封装的字段。
propertyGrid1.SelectedObject = new Level1();public class Level1
{private
SEO靠我 int nVal1;private int nVal2;private int nVal3;public int NVal1 { get => nVal1; set => nVal1 = value
SEO靠我; }public int NVal2 { get => nVal2; set => nVal2 = value; }public int NVal3 { get => nVal3; set => n
SEO靠我Val3 = value; }
}
propertyGrid1.SelectedObjects = new object[] { new Level1(), new Level2() }SEO靠我;
显示Level2 和 Level2 中所有公共属性
propertyGrid1.SelectedObjects = new object[] { new Level1(), n
SEO靠我ew Level2() };public class Level1
{private int nVal1;private int nVal2;private int nVal3;pub
SEO靠我lic int NVal1 { get => nVal1; set => nVal1 = value; }public int NVal2 { get => nVal2; set => nVal2 =
SEO靠我 value; }public int NVal3 { get => nVal3; set => nVal3 = value; }
}
public class Lev
SEO靠我el2
{private int nVal3;private int nVal4;private int nVal5;public int NVal3 { get => nVal3;
SEO靠我set => nVal3 = value; }public int NVal4 { get => nVal4; set => nVal4 = value; }public int NVal5 { ge
SEO靠我t => nVal5; set => nVal5 = value; }
}
二、 PropertyGrid 的简单属性配置
BackColor 更改其背景色。HelpBackColor 更
SEO靠我改助窗口背景色。HelpForeColor 更改助窗口字体颜色。HelpVisible 显示隐藏帮助窗口。ToolbarVisible 显示隐藏工具栏。LargeButtons 显示大型工具栏按钮。P
SEO靠我ropertySort 按字母顺序对属性进行排序。BackColor 更改拆分器颜色。LineColor 更改网格线和边框。
三、 设置字段属性
DescriptionAttribute - 设置属性在属
SEO靠我性下方的说明帮助窗格中显示的属性的文本。 这是为具有焦点的活动属性提供帮助文本的有用方法。 将此属性应用于 MaxRepeatRate 该属性。CategoryAttribute 设置属性在网格中所属
SEO靠我的类别。 当需要按类别名称分组的属性时,这非常有用。 如果属性未指定类别,则会将其分配给 Misc 类别。 将此属性应用于所有属性。BrowsableAttribute – 指示属性是否显示在网格中。
SEO靠我 如果要从网格中隐藏属性,这非常有用。 默认情况下,公共属性始终显示在网格中。 将此属性应用于 SettingsChanged 该属性。ReadOnlyAttribute – 指示属性是否为只读。 如
SEO靠我果要使属性在网格中不可编辑,这非常有用。 默认情况下,具有 get 和 set 访问器函数的公共属性在网格中可编辑。 将此属性应用于 AppVersion 该属性。DefaultValueAttrib
SEO靠我ute – 标识属性的默认值。 如果想要为属性提供默认值,然后确定该属性的值是否不同于默认值,则这非常有用。 将此属性应用于所有属性。DefaultPropertyAttribute – 标识类的默认
SEO靠我属性。 类的默认属性在网格中选择类时首先获取焦点。 将此属性应用于 AppSettings 类。DisplayNameAttribute - 实际显示的名称
[DefaultProp
SEO靠我erty("NVal1")]
public class Level1
{private int nVal1;private int nVal2;private int
SEO靠我nVal3;[Category("Level"), DefaultValue("123"), ReadOnly(false), Browsable(true), Description("This I
SEO靠我s Description")]public int NVal1 { get => nVal1; set => nVal1 = value; }[Category("Level"),Browsable
SEO靠我(false)]public int NVal2 { get => nVal2; set => nVal2 = value; }[Category("Level"), DefaultValue("45
SEO靠我6"), ReadOnly(true)]public int NVal3 { get => nVal3; set => nVal3 = value; }
}
四、 字段的下拉框
常用属性 SEO靠我PropertyGrid 中已经封装了下拉框属性
字符串:
1. 通过继承重写 StringConverter 函数
/* 创建从类型转换器类继承的类。 * 由于属性 DefaultFileName 属于
SEO靠我String 类型* 因此可以从 StringConverter 继承。 * 如果属性类型的类型转换器不存在,则可以从 * TypeConverter 继承;在这种情况下,不需要这样做。*/
SEO靠我 public class MyStringConverter : StringConverter
{
//重写 GetStandardValuesSupport
SEO靠我ed 方法并返回 true 以指示此对象支持可从列表中选择的标准值集。
public override bool GetStandardValuesSupported( ITypeDe
SEO靠我scriptorContext context)
{return true;
}/* 重写 GetStandardValues 方法,并返回用标准值填充的 Standa
SEO靠我rdValuesCollection 。 * 创建 StandardValuesCollection 的一种方法是在构造函数中提供值数组。 * 对于选项窗口应用程序,可以使用填充有建议的默认文件名的
SEO靠我字符串 数组。*/
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext
SEO靠我context)
{return new StandardValuesCollection(new string[]{"Str2", "Str3", "Str4"});
SEO靠我 }/* (可选) 如果希望用户能够键入不在下拉列表中的值,* 请重写 GetStandardValuesExclusive 方法并返回 false。 * 这基本上将下拉列表样式更改为组合框样式。*/
SEO靠我
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{re
SEO靠我turn false;
}
2. 通过Enum.ToString()实现,将String[] 变为 Enum,通过 Enum 实现下拉框
public class Level1
SEO靠我 {private bool bVal = true;private Size sizeVal = new Size(100,200);private Font fontVal= new Font
SEO靠我("宋体", 9, FontStyle.Regular);private Color colVal = Color.Red;private EnumVal eVal = EnumVal.E02;pri
SEO靠我vate String sVal = "Str1";[CategoryAttribute("下拉框")]public bool BVal { get => bVal; set => bVal = va
SEO靠我lue; }[CategoryAttribute("下拉框")]public Size SizeVal { get => sizeVal; set => sizeVal = value; }[Cate
SEO靠我goryAttribute("下拉框")]public Font FontVal { get => fontVal; set => fontVal = value; }[CategoryAttribu
SEO靠我te("下拉框")]public Color ColVal { get => colVal; set => colVal = value; }[CategoryAttribute("下拉框")]pub
SEO靠我lic EnumVal EVal { get => eVal; set => eVal = value; }[CategoryAttribute("下拉框"), TypeConverter(typeo
SEO靠我f(MyStringConverter))]public string SVal { get => sVal; set => sVal = value; }
}
五、 多级展开
publi
SEO靠我c class Level1
{private SpellingOptions spell = new SpellingOptions();/* 6. 将 TypeConverterA
SEO靠我ttribute 应用于示例中的类 SpellingOptions 目标类。*/[TypeConverterAttribute(typeof(SpellingOptionsConverter))]pu
SEO靠我blic SpellingOptions Spell { get => spell; set => spell = value; }
}public class SpellingOpt
SEO靠我ions
{private bool spellCheckWhileTyping = true;private bool spellCheckCAPS = false;private
SEO靠我bool suggestCorrections = true;[DefaultValueAttribute(true)]public bool SpellCheckWhileTyping{get {
SEO靠我return spellCheckWhileTyping; }set { spellCheckWhileTyping = value; }}[DefaultValueAttribute(false)]
SEO靠我public bool SpellCheckCAPS{get { return spellCheckCAPS; }set { spellCheckCAPS = value; }}[DefaultVal
SEO靠我ueAttribute(true)]public bool SuggestCorrections{get { return suggestCorrections; }set { suggestCorr
SEO靠我ections = value; }}
}/* 1. 创建继承自 ExpandableObjectConverter 的类。* 若要获取 PropertyGrid 以展开 Spelli
SEO靠我ngOptions 该属性,需要创建 TypeConverter。 * TypeConverter 提供了一种从一种类型转换为另一种类型的方法。 * PropertyGrid 使用 TypeConve
SEO靠我rter 将对象类型转换为字符串,该字符串用于在网格中显示对象值。 * 在编辑期间, TypeConverter 将从 String 转换回对象类型。 * .NET Framework提供了 Expa
SEO靠我ndableObjectConverter 类,以便更轻松地执行此操作。*/
public class SpellingOptionsConverter : ExpandableObj
SEO靠我ectConverter
{/* 2. 如果参数与使用此类型的SpellingOptions转换器的类相同,* 则重写 CanConvertTo 方法并返回 truedestinati
SEO靠我onType;* 否则,返回基类 CanConvertTo 方法的值。*/ public override bool CanConvertTo(ITypeDescriptorContext conte
SEO靠我xt, System.Type destinationType){if (destinationType == typeof(SpellingOptions))return true;return b
SEO靠我ase.CanConvertTo(context, destinationType);}/* 3. 重写 ConvertTo 方法,并确保 destinationType 参数是 字符串 ,* 并且该
SEO靠我值与使用此类型转换器 SpellingOptions 的类(示例中的类) 的类型相同。 * 如果任一情况为 false,则返回基类 ConvertTo 方法的值;* 否则返回值对象的字符串表示形式。
SEO靠我字符串表示形式需要用唯一分隔符分隔类的每个属性。 * 由于整个字符串将显示在 PropertyGrid 中,* 因此你需要选择一个不减去可读性的分隔符;逗号通常效果良好。*/ public overr
SEO靠我ide object ConvertTo(ITypeDescriptorContext context,CultureInfo culture,object value,System.Type des
SEO靠我tinationType){if (destinationType == typeof(System.String) &&value is SpellingOptions){SpellingOptio
SEO靠我ns so = (SpellingOptions)value;return "Typing:" + so.SpellCheckWhileTyping +", CAPS: " + so.SpellChe
SEO靠我ckCAPS +", Suggest: " + so.SuggestCorrections;}return base.ConvertTo(context, culture, value, destin
SEO靠我ationType);}/* 4. (可选) 可以通过指定类型转换器可以从字符串转换来启用对网格中* 对象的字符串表示形式的编辑。 为此,请先重写 CanConvertFrom 方法,* 如果源 Ty
SEO靠我pe 参数的类型为 String,则返回 true;否则,* 返回基类 CanConvertFrom 方法的值。*/ public override bool CanConvertFrom(IType
SEO靠我DescriptorContext context,System.Type sourceType){if (sourceType == typeof(string))return true;retur
SEO靠我n base.CanConvertFrom(context, sourceType);}/* 5. 若要启用对对象的基类的编辑,* 还需要重写 ConvertFrom 方法,并确保值参数为 Strin
SEO靠我g。 * 如果不是 String,则返回基类 ConvertFrom 方法的值;* 否则,请根据值参数返回类的新实例, (SpellingOptions 示例中的类) 。 * 需要从值参数分析类的每个
SEO靠我属性的值。 * 了解在 ConvertTo 方法中创建的带分隔符的字符串的格式将有助于执行分析。*/public override object ConvertFrom(ITypeDescriptor
SEO靠我Context context, CultureInfo culture, object value){if (value is string){try{string s = (string)valu
SEO靠我e;int colon = s.IndexOf(:);int comma = s.IndexOf(,);if (colon != -1 && comma != -1){string checkWhil
SEO靠我eTyping = s.Substring(colon + 1,(comma - colon - 1));colon = s.IndexOf(:, comma + 1);comma = s.Index
SEO靠我Of(,, comma + 1);string checkCaps = s.Substring(colon + 1,(comma - colon - 1));colon = s.IndexOf(:,
SEO靠我comma + 1);string suggCorr = s.Substring(colon + 1);SpellingOptions so = new SpellingOptions();so.Sp
SEO靠我ellCheckWhileTyping = Boolean.Parse(checkWhileTyping);so.SpellCheckCAPS = Boolean.Parse(checkCaps);s
SEO靠我o.SuggestCorrections = Boolean.Parse(suggCorr);return so;}}catch{throw new ArgumentException( "Can n
SEO靠我ot convert " + (string)value + " to type SpellingOptions");}}return base.ConvertFrom(context, cultur
SEO靠我e, value);}
}
六、 显示内容的排序
6.1 属性排序
PropertyGrid 默认支持的排序方式自定义顺序的排序方式根据字段封装顺序的排序方式
6.1.1 自定义排序
[Type
SEO靠我Converter(typeof(PropertySorter))]
public class Level1
{int n01 = 1;int n02 = 2;int
SEO靠我n03 = 3;int n04 = 4;int n05 = 5;int n06 = 6;[PropertyOrder(1)]public int N01 { get => n01; set => n0
SEO靠我1 = value; }[PropertyOrder(2)]public int N04 { get => n04; set => n04 = value; }[PropertyOrder(3)]pu
SEO靠我blic int N02 { get => n02; set => n02 = value; }[PropertyOrder(4)]public int N05 { get => n05; set =
SEO靠我> n05 = value; }[PropertyOrder(5)]public int N03 { get => n03; set => n03 = value; }[PropertyOrder(6
SEO靠我)]public int N06 { get => n06; set => n06 = value; }
}public class PropertySorter : Expandab
SEO靠我leObjectConverter
{public override bool GetPropertiesSupported(ITypeDescriptorContext contex
SEO靠我t){return true;}public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext co
SEO靠我ntext, object value, Attribute[] attributes){//// This override returns a list of properties in orde
SEO靠我r//PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(value, attributes);ArrayList orde
SEO靠我redProperties = new ArrayList();foreach (PropertyDescriptor pd in pdc){Attribute attribute = pd.Attr
SEO靠我ibutes[typeof(PropertyOrderAttribute)];if (attribute != null){//// If the attribute is found, then c
SEO靠我reate an pair object to hold it//PropertyOrderAttribute poa = (PropertyOrderAttribute)attribute;orde
SEO靠我redProperties.Add(new PropertyOrderPair(pd.Name, poa.Order));}else{//// If no order attribute is spe
SEO靠我cifed then given it an order of 0//orderedProperties.Add(new PropertyOrderPair(pd.Name, 0));}}//// P
SEO靠我erform the actual order using the value PropertyOrderPair classes// implementation of IComparable to
SEO靠我 sort//orderedProperties.Sort();//// Build a string list of the ordered names//ArrayList propertyNam
SEO靠我es = new ArrayList();foreach (PropertyOrderPair pop in orderedProperties){propertyNames.Add(pop.Name
SEO靠我);}//// Pass in the ordered list for the PropertyDescriptorCollection to sort by//return pdc.Sort((s
SEO靠我tring[])propertyNames.ToArray(typeof(string)));}
}[AttributeUsage(AttributeTargets.Property)
SEO靠我]
public class PropertyOrderAttribute : Attribute
{//// Simple attribute to allow th
SEO靠我e order of a property to be specified//private int _order;public PropertyOrderAttribute(int order){_
SEO靠我order = order;}public int Order{get{return _order;}}
}public class PropertyOrderPair : IComp
SEO靠我arable
{private int _order;private string _name;public string Name{get{return _name;}}public
SEO靠我 PropertyOrderPair(string name, int order){_order = order;_name = name;}public int CompareTo(object
SEO靠我obj){//// Sort the pair objects by ordering by order value// Equal values get the same rank//int oth
SEO靠我erOrder = ((PropertyOrderPair)obj)._order;if (otherOrder == _order){//// If order not specified, sor
SEO靠我t by name//string otherName = ((PropertyOrderPair)obj)._name;return string.Compare(_name, otherName)
SEO靠我;}else if (otherOrder > _order){return -1;}return 1;}
}
6.1.2 根据字段封装顺序
[TypeConverter(typeof(P
SEO靠我ropertySorter))]
public class Level1
{int n01 = 1;int n02 = 2;int n03 = 3;int n04 =
SEO靠我4;int n05 = 5;int n06 = 6;public int N01 { get => n01; set => n01 = value; }public int N04 { get =>
SEO靠我n04; set => n04 = value; }public int N02 { get => n02; set => n02 = value; }public int N05 { get =>
SEO靠我n05; set => n05 = value; }public int N03 { get => n03; set => n03 = value; }public int N06 { get =>
SEO靠我n06; set => n06 = value; }
}public class PropertySorter : ExpandableObjectConverter
SEO靠我{public override bool GetPropertiesSupported(ITypeDescriptorContext context){return true;}public ove
SEO靠我rride PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attri
SEO靠我bute[] attributes){PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(value, attributes
SEO靠我);ArrayList propertyNames = new ArrayList();foreach (PropertyDescriptor pd in pdc)propertyNames.Add(
SEO靠我pd.Name);return pdc.Sort((string[])propertyNames.ToArray(typeof(string)));}
}
6.2 类别排序
1. PropSEO靠我ertyGrid.PropertySort = CategorizedAlphabetical
2. 数据类中添加类别排序List
private List<String> categorys = new
SEO靠我 List<string>() { ... };
3. 添加 PropertyGrid 的 Paint 事件
private void propertyGrid1_Paint(object sender,
SEO靠我 PaintEventArgs e)
{var categorysinfo = propertyGrid1.SelectedObject.GetType().GetField("cat
SEO靠我egorys", BindingFlags.NonPublic | BindingFlags.Instance);if (categorysinfo != null){var categorys =
SEO靠我categorysinfo.GetValue(propertyGrid1.SelectedObject) as List<String>;propertyGrid1.CollapseAllGridIt
SEO靠我ems();GridItemCollection currentPropEntries = typeof(PropertyGrid).GetField("currentPropEntries", Bi
SEO靠我ndingFlags.NonPublic | BindingFlags.Instance).GetValue(propertyGrid1) as GridItemCollection;var newa
SEO靠我rray = currentPropEntries.Cast<GridItem>().OrderBy((t) => categorys.IndexOf(t.Label)).ToArray();curr
SEO靠我entPropEntries.GetType().GetField("entries", BindingFlags.NonPublic | BindingFlags.Instance).SetValu
SEO靠我e(currentPropEntries, newarray);propertyGrid1.ExpandAllGridItems();object obj = propertyGrid1.Tag;if
SEO靠我 (obj != null)propertyGrid1.PropertySort = (PropertySort)obj;}propertyGrid1.Paint -= new PaintEventH
SEO靠我andler(propertyGrid1_Paint);propertyGrid1.CollapseAllGridItems();
}
七、 闪屏问题
Form.DoubleBuffereSEO靠我d = true; 或者 SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
八、 主要参考
充分利用 .NET Framework PropertySEO靠我Grid 控件 | Microsoft Learn
c# PropertyGrid 自定义属性排序_楚楚3107的博客-CSDN博客
PropertyGrid控件 分类(Category)及属性(PropSEO靠我erty)排序_propertygrid 排序_衣舞晨风的博客-CSDN博客