C# PropertyGrid 简单使用

这篇具有很好参考价值的文章主要介绍了C# PropertyGrid 简单使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、 导入数据

二、 PropertyGrid 的简单属性配置

三、 设置字段属性

四、 字段的下拉框

五、 多级展开

六、 显示内容的排序

6.1 属性排序

6.1.1 自定义排序

6.1.2 根据字段封装顺序

6.2 类别排序 

七、 闪屏问题

八、 主要参考


一、 导入数据

propertyGrid1.SelectedObject = new Level1(); 

  • 显示Level1类中所有 public 属性 Get Set 封装的字段。

C# PropertyGrid 简单使用

propertyGrid1.SelectedObject = new Level1();

public class Level1
{
    private int nVal1;
    private int nVal2;
    private int nVal3;

    public int NVal1 { get => nVal1; set => nVal1 = value; }
    public int NVal2 { get => nVal2; set => nVal2 = value; }
    public int NVal3 { get => nVal3; set => nVal3 = value; }
}

propertyGrid1.SelectedObjects = new object[] { new Level1(), new Level2() };

  • 显示Level2 和 Level2 中所有公共属性 

 C# PropertyGrid 简单使用

propertyGrid1.SelectedObjects = new object[] { new Level1(), new Level2() };

public class Level1
{
    private int nVal1;
    private int nVal2;
    private int nVal3;

    public int NVal1 { get => nVal1; set => nVal1 = value; }
    public int NVal2 { get => nVal2; set => nVal2 = value; }
    public int NVal3 { get => nVal3; set => nVal3 = value; }
}
public class Level2
{
    private int nVal3;
    private int nVal4;
    private int nVal5;

    public int NVal3 { get => nVal3; set => nVal3 = value; }
    public int NVal4 { get => nVal4; set => nVal4 = value; }
    public int NVal5 { get => nVal5; set => nVal5 = value; }
}

二、 PropertyGrid 的简单属性配置

  • BackColor 更改其背景色。
  • HelpBackColor 更改助窗口背景色。
  • HelpForeColor 更改助窗口字体颜色。
  • HelpVisible 显示隐藏帮助窗口。
  • ToolbarVisible 显示隐藏工具栏。
  • LargeButtons 显示大型工具栏按钮。
  • PropertySort 按字母顺序对属性进行排序。
  • BackColor 更改拆分器颜色。
  • LineColor 更改网格线和边框。

三、 设置字段属性

  • DescriptionAttribute - 设置属性在属性下方的说明帮助窗格中显示的属性的文本。 这是为具有焦点的活动属性提供帮助文本的有用方法。 将此属性应用于 MaxRepeatRate 该属性。
  • CategoryAttribute 设置属性在网格中所属的类别。 当需要按类别名称分组的属性时,这非常有用。 如果属性未指定类别,则会将其分配给 Misc 类别。 将此属性应用于所有属性。
  • BrowsableAttribute – 指示属性是否显示在网格中。 如果要从网格中隐藏属性,这非常有用。 默认情况下,公共属性始终显示在网格中。 将此属性应用于 SettingsChanged 该属性。
  • ReadOnlyAttribute – 指示属性是否为只读。 如果要使属性在网格中不可编辑,这非常有用。 默认情况下,具有 get 和 set 访问器函数的公共属性在网格中可编辑。 将此属性应用于 AppVersion 该属性。
  • DefaultValueAttribute – 标识属性的默认值。 如果想要为属性提供默认值,然后确定该属性的值是否不同于默认值,则这非常有用。 将此属性应用于所有属性。
  • DefaultPropertyAttribute – 标识类的默认属性。 类的默认属性在网格中选择类时首先获取焦点。 将此属性应用于 AppSettings 类。
  • DisplayNameAttribute - 实际显示的名称

 C# PropertyGrid 简单使用

[DefaultProperty("NVal1")]
public class Level1
{
    private int nVal1;
    private int nVal2;
    private int nVal3;

    [Category("Level"), DefaultValue("123"), ReadOnly(false), Browsable(true), Description("This Is Description")]
    public int NVal1 { get => nVal1; set => nVal1 = value; }

    [Category("Level"),Browsable(false)]
    public int NVal2 { get => nVal2; set => nVal2 = value; }

    [Category("Level"), DefaultValue("456"), ReadOnly(true)]
    public int NVal3 { get => nVal3; set => nVal3 = value; }
}

四、 字段的下拉框

常用属性 PropertyGrid 中已经封装了下拉框属性 

字符串:

1. 通过继承重写 StringConverter 函数

/* 创建从类型转换器类继承的类。 
 * 由于属性 DefaultFileName 属于 String 类型
 * 因此可以从 StringConverter 继承。 
 * 如果属性类型的类型转换器不存在,则可以从 
 * TypeConverter 继承;在这种情况下,不需要这样做。
 */ 
public class MyStringConverter : StringConverter
{
//重写 GetStandardValuesSupported 方法并返回 true 以指示此对象支持可从列表中选择的标准值集。
public override bool GetStandardValuesSupported( ITypeDescriptorContext context)
{
    return true;
}

/* 重写 GetStandardValues 方法,并返回用标准值填充的 StandardValuesCollection 。 
 * 创建 StandardValuesCollection 的一种方法是在构造函数中提供值数组。 
 * 对于选项窗口应用程序,可以使用填充有建议的默认文件名的 字符串 数组。
 */ 
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
    return new StandardValuesCollection(new string[]{"Str2", "Str3", "Str4"});
}

/* (可选) 如果希望用户能够键入不在下拉列表中的值,
 * 请重写 GetStandardValuesExclusive 方法并返回 false。 
 * 这基本上将下拉列表样式更改为组合框样式。
 */ 
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
    return false;
}

2. 通过Enum.ToString()实现,将String[] 变为 Enum,通过 Enum 实现下拉框

public class Level1
{
	private bool bVal = true;
	private Size sizeVal = new Size(100,200);
	private Font fontVal= new Font("宋体", 9, FontStyle.Regular);
	private Color colVal = Color.Red;
	private EnumVal eVal = EnumVal.E02;
    private String sVal = "Str1";

	[CategoryAttribute("下拉框")]
	public bool BVal { get => bVal; set => bVal = value; }
	[CategoryAttribute("下拉框")]
	public Size SizeVal { get => sizeVal; set => sizeVal = value; }
	[CategoryAttribute("下拉框")]
	public Font FontVal { get => fontVal; set => fontVal = value; }
	[CategoryAttribute("下拉框")]
	public Color ColVal { get => colVal; set => colVal = value; }
	[CategoryAttribute("下拉框")]
	public EnumVal EVal { get => eVal; set => eVal = value; }
    [CategoryAttribute("下拉框"), TypeConverter(typeof(MyStringConverter))]
    public string SVal { get => sVal; set => sVal = value; }
}

五、 多级展开

C# PropertyGrid 简单使用

public class Level1
{
	private SpellingOptions spell = new SpellingOptions();

	/* 6. 将 TypeConverterAttribute 应用于示例中的类 SpellingOptions 目标类。
	 */
	[TypeConverterAttribute(typeof(SpellingOptionsConverter))]
	public SpellingOptions Spell { get => spell; set => spell = value; }
}

public class SpellingOptions
{
	private bool spellCheckWhileTyping = true;
	private bool spellCheckCAPS = false;
	private bool suggestCorrections = true;

	[DefaultValueAttribute(true)]
	public bool SpellCheckWhileTyping
	{
		get { return spellCheckWhileTyping; }
		set { spellCheckWhileTyping = value; }
	}

	[DefaultValueAttribute(false)]
	public bool SpellCheckCAPS
	{
		get { return spellCheckCAPS; }
		set { spellCheckCAPS = value; }
	}
	[DefaultValueAttribute(true)]
	public bool SuggestCorrections
	{
		get { return suggestCorrections; }
		set { suggestCorrections = value; }
	}
}

   
/* 1. 创建继承自 ExpandableObjectConverter 的类。
 * 若要获取 PropertyGrid 以展开 SpellingOptions 该属性,需要创建 TypeConverter。 
 * TypeConverter 提供了一种从一种类型转换为另一种类型的方法。 
 * PropertyGrid 使用 TypeConverter 将对象类型转换为字符串,该字符串用于在网格中显示对象值。 
 * 在编辑期间, TypeConverter 将从 String 转换回对象类型。 
 * .NET Framework提供了 ExpandableObjectConverter 类,以便更轻松地执行此操作。
 */
public class SpellingOptionsConverter : ExpandableObjectConverter
{
	/* 2. 如果参数与使用此类型的SpellingOptions转换器的类相同,
	 * 则重写 CanConvertTo 方法并返回 truedestinationType;
	 * 否则,返回基类 CanConvertTo 方法的值。
	 */ 
	public override bool CanConvertTo(ITypeDescriptorContext context, System.Type destinationType)
	{
		if (destinationType == typeof(SpellingOptions))
			return true;

		return base.CanConvertTo(context, destinationType);
	}

	/* 3. 重写 ConvertTo 方法,并确保 destinationType 参数是 字符串 ,
	 * 并且该值与使用此类型转换器 SpellingOptions 的类(示例中的类) 的类型相同。 
	 * 如果任一情况为 false,则返回基类 ConvertTo 方法的值;
	 * 否则返回值对象的字符串表示形式。 字符串表示形式需要用唯一分隔符分隔类的每个属性。 
	 * 由于整个字符串将显示在 PropertyGrid 中,
	 * 因此你需要选择一个不减去可读性的分隔符;逗号通常效果良好。
	 */ 
	public override object ConvertTo(ITypeDescriptorContext context,
	   CultureInfo culture,
	   object value,
	   System.Type destinationType)
	{
		if (destinationType == typeof(System.String) &&
		 value is SpellingOptions)
		{
			SpellingOptions so = (SpellingOptions)value;

			return "Typing:" + so.SpellCheckWhileTyping +
			   ", CAPS: " + so.SpellCheckCAPS +
			   ", Suggest: " + so.SuggestCorrections;
		}
		return base.ConvertTo(context, culture, value, destinationType);
	}

	/* 4. (可选) 可以通过指定类型转换器可以从字符串转换来启用对网格中
	 * 对象的字符串表示形式的编辑。 为此,请先重写 CanConvertFrom 方法,
	 * 如果源 Type 参数的类型为 String,则返回 true;否则,
	 * 返回基类 CanConvertFrom 方法的值。
	 */ 
	public override bool CanConvertFrom(ITypeDescriptorContext context,
	  System.Type sourceType)
	{
		if (sourceType == typeof(string))
			return true;

		return base.CanConvertFrom(context, sourceType);
	}

	/* 5. 若要启用对对象的基类的编辑,
	 * 还需要重写 ConvertFrom 方法,并确保值参数为 String。 
	 * 如果不是 String,则返回基类 ConvertFrom 方法的值;
	 * 否则,请根据值参数返回类的新实例, (SpellingOptions 示例中的类) 。 
	 * 需要从值参数分析类的每个属性的值。 
	 * 了解在 ConvertTo 方法中创建的带分隔符的字符串的格式将有助于执行分析。
	 */
	public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
	{
		if (value is string)
		{
			try
			{
				string s = (string)value;
				int colon = s.IndexOf(':');
				int comma = s.IndexOf(',');

				if (colon != -1 && comma != -1)
				{
					string checkWhileTyping = s.Substring(colon + 1,
					(comma - colon - 1));

					colon = s.IndexOf(':', comma + 1);
					comma = s.IndexOf(',', comma + 1);

					string checkCaps = s.Substring(colon + 1,
					(comma - colon - 1));

					colon = s.IndexOf(':', comma + 1);

					string suggCorr = s.Substring(colon + 1);

					SpellingOptions so = new SpellingOptions();

					so.SpellCheckWhileTyping = Boolean.Parse(checkWhileTyping);
					so.SpellCheckCAPS = Boolean.Parse(checkCaps);
					so.SuggestCorrections = Boolean.Parse(suggCorr);

					return so;
				}
			}
			catch
			{
				throw new ArgumentException( "Can not convert '" + (string)value + "' to type SpellingOptions");
			}
		}
		return base.ConvertFrom(context, culture, value);
	}
}

六、 显示内容的排序

6.1 属性排序

  • PropertyGrid 默认支持的排序方式
  • 自定义顺序的排序方式
  • 根据字段封装顺序的排序方式

C# PropertyGrid 简单使用C# PropertyGrid 简单使用  

6.1.1 自定义排序

[TypeConverter(typeof(PropertySorter))]
public class Level1
{
	int n01 = 1;
	int n02 = 2;
	int n03 = 3;
	int n04 = 4;
	int n05 = 5;
	int n06 = 6;

	[PropertyOrder(1)]
	public int N01 { get => n01; set => n01 = value; }
	[PropertyOrder(2)]
	public int N04 { get => n04; set => n04 = value; }
	[PropertyOrder(3)]
	public int N02 { get => n02; set => n02 = value; }
	[PropertyOrder(4)]
	public int N05 { get => n05; set => n05 = value; }
	[PropertyOrder(5)]
	public int N03 { get => n03; set => n03 = value; }
	[PropertyOrder(6)]
	public int N06 { get => n06; set => n06 = value; }
}


public class PropertySorter : ExpandableObjectConverter
{
	public override bool GetPropertiesSupported(ITypeDescriptorContext context)
	{
		return true;
	}


	public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
	{
		//
		// This override returns a list of properties in order
		//
		PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(value, attributes);
		ArrayList orderedProperties = new ArrayList();
		foreach (PropertyDescriptor pd in pdc)
		{
			Attribute attribute = pd.Attributes[typeof(PropertyOrderAttribute)];
			if (attribute != null)
			{
				//
				// If the attribute is found, then create an pair object to hold it
				//
				PropertyOrderAttribute poa = (PropertyOrderAttribute)attribute;
				orderedProperties.Add(new PropertyOrderPair(pd.Name, poa.Order));
			}
			else
			{
				//
				// If no order attribute is specifed then given it an order of 0
				//
				orderedProperties.Add(new PropertyOrderPair(pd.Name, 0));
			}
		}
		//
		// Perform the actual order using the value PropertyOrderPair classes
		// implementation of IComparable to sort
		//
		orderedProperties.Sort();
		//
		// Build a string list of the ordered names
		//
		ArrayList propertyNames = new ArrayList();
		foreach (PropertyOrderPair pop in orderedProperties)
		{
			propertyNames.Add(pop.Name);
		}
		//
		// Pass in the ordered list for the PropertyDescriptorCollection to sort by
		//
		return pdc.Sort((string[])propertyNames.ToArray(typeof(string)));
	}
}


[AttributeUsage(AttributeTargets.Property)]
public class PropertyOrderAttribute : Attribute
{
	//
	// Simple attribute to allow the order of a property to be specified
	//
	private int _order;
	public PropertyOrderAttribute(int order)
	{
		_order = order;
	}

	public int Order
	{
		get
		{
			return _order;
		}
	}
}


public class PropertyOrderPair : IComparable
{
	private int _order;
	private string _name;

	public string Name
	{
		get
		{
			return _name;
		}
	}

	public PropertyOrderPair(string name, int order)
	{
		_order = order;
		_name = name;
	}
	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;
	}
}

6.1.2 根据字段封装顺序

[TypeConverter(typeof(PropertySorter))]
public class Level1
{
	int n01 = 1;
	int n02 = 2;
	int n03 = 3;
	int n04 = 4;
	int n05 = 5;
	int n06 = 6;

	public int N01 { get => n01; set => n01 = value; }
	public int N04 { get => n04; set => n04 = value; }
	public int N02 { get => n02; set => n02 = value; }
	public int N05 { get => n05; set => n05 = value; }
	public int N03 { get => n03; set => n03 = value; }
	public int N06 { get => n06; set => n06 = value; }
}

public class PropertySorter : ExpandableObjectConverter
{
	public override bool GetPropertiesSupported(ITypeDescriptorContext context)
	{
		return true;
	}

	public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
	{
		PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(value, attributes);
		ArrayList propertyNames = new ArrayList();
		foreach (PropertyDescriptor pd in pdc)
		propertyNames.Add(pd.Name);
		return pdc.Sort((string[])propertyNames.ToArray(typeof(string)));
	}
}

6.2 类别排序 

1. PropertyGrid.PropertySort = CategorizedAlphabetical

2. 数据类中添加类别排序List

private List<String> categorys = new List<string>() { ... };

 3. 添加 PropertyGrid 的 Paint 事件

private void propertyGrid1_Paint(object sender, PaintEventArgs e)
{
	var categorysinfo = propertyGrid1.SelectedObject.GetType().GetField("categorys", BindingFlags.NonPublic | BindingFlags.Instance);
	if (categorysinfo != null)
	{
		var categorys = categorysinfo.GetValue(propertyGrid1.SelectedObject) as List<String>;
		propertyGrid1.CollapseAllGridItems();
		GridItemCollection currentPropEntries = typeof(PropertyGrid).GetField("currentPropEntries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(propertyGrid1) as GridItemCollection;
		var newarray = currentPropEntries.Cast<GridItem>().OrderBy((t) => categorys.IndexOf(t.Label)).ToArray();
		currentPropEntries.GetType().GetField("entries", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(currentPropEntries, newarray);
		propertyGrid1.ExpandAllGridItems();
		object obj = propertyGrid1.Tag;
		if (obj != null)
			propertyGrid1.PropertySort = (PropertySort)obj;
	}
	propertyGrid1.Paint -= new PaintEventHandler(propertyGrid1_Paint);
	propertyGrid1.CollapseAllGridItems();
}

七、 闪屏问题

Form.DoubleBuffered = true; 或者 SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

八、 主要参考

充分利用 .NET Framework PropertyGrid 控件 | Microsoft Learn

c# PropertyGrid 自定义属性排序_楚楚3107的博客-CSDN博客

PropertyGrid控件 分类(Category)及属性(Property)排序_propertygrid 排序_衣舞晨风的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-434946.html

到了这里,关于C# PropertyGrid 简单使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包