很早之前写的一个例子,近期看到了,就简单记录下。
PropertyGrid控件是Visual Studio开发工具里面的属性浏览器,我们在VS里面可以通过属性浏览器查看,修改控件的属性。
选择对象
要标识 PropertyGrid 显示的内容,需将 PropertyGrid.SelectedObject 属性设置为一个对象实例。
然后,PropertyGrid 将完成其余的工作。每次设置 SelectedObject 时,PropertyGrid 都会刷新显示的属性。
这提供了一种简单的方法来强制刷新属性,或在运行时切换对象。您还可以调用 PropertyGrid.Refresh 方法来刷新属性。
创建一个 AppSettings 对象,并将其设置为 PropertyGrid.SelectedObject 属性的值。
AppSetting setting = new AppSetting();
this.propertyGrid.SelectedObject = setting;
属性描述
DescriptionAttribute:设置显示在属性下方说明帮助窗格中的属性文本
CategoryAttribute:设置属性在网格中所属的类别
Browsable:在网格中是否显示属性
ReadOnly:设置属性只读
DefaultValue:表示属性的默认值,修改值之后,字体会加粗黑体
普通属性
private int _width = 10;
[Browsable(true)]
[Category("简单属性")]
[Description("设置整型")]
[DefaultValue(10)]
public int Width
{
get { return _width; }
set { _width = value; }
}
private string _name = "Jack";
[Category("简单属性")]
[Description("设置字符串")]
[DefaultValue("Jack")]
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
private Size _windowSize = new Size(100, 100);
[Browsable(true)]
[Category("简单属性")]
[Description("窗体尺寸")]
public Size WindowSize
{
get
{
return _windowSize;
}
set
{
_windowSize = value;
}
}
private Font _windowFont = new Font("宋体", 9, FontStyle.Regular);
[Browsable(true)]
[Category("简单属性")]
[Description("字体")]
public Font Font
{
get
{
return _windowFont;
}
set
{
_windowFont = value;
}
}
private Color _color = SystemColors.Control;
[Browsable(true)]
[Category("简单属性")]
[Description("颜色")]
public Color Color
{
get
{
return _color;
}
set
{
_color= value;
}
}
具体效果如下:
下拉列表
//性别枚举类
public enum Sex
{
male = 1,
female = 2
}
private Sex _sex = Sex.male;
[Browsable(true)]
[Category("简单属性")]
[DescriptionAttribute("枚举")]
[DefaultValue(Sex.male)]
public Sex Sex
{
get
{
return _sex;
}
set
{
_sex = value;
}
}
具体效果如下:
自定义下拉列表
private string _defaultFileName = string.Empty;
[Category("下拉列表")]
[Description("自定义下拉列表")]
[Browsable(true)]
[TypeConverter(typeof(FileNameConverter))]
public string DefaultFileName
{
get
{
return _defaultFileName;
}
set
{
_defaultFileName = value;
}
}
/// <summary>
/// 创建一个继承自定义转换器类的类,由于DefaultFileName属性是String类型,因此可以从StringConverter继承。
/// 如果属性类型的类型转换器不存在,
/// 则可以继承TypeConverter
/// </summary>
public class FileNameConverter:StringConverter
{
/// <summary>
/// 重写GetStandardValuesSupported方法并返回true.
/// 以指示此对象支持可从列表中选取的一组标准值。
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
/// <summary>
/// 检索一个集合,该集合包含适用于此验证程序的数据类型的标准值集。 如果该数据类型不支持标准值集,这将返回 null。
/// </summary>
/// <param name="context">格式化程序上下文</param>
/// <returns>包含 null 或标准有效值集的集合</returns>
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
StandardValuesCollection collection = new StandardValuesCollection(new String[] { "诸葛亮", "诸葛暗", "诸葛孔明", });
return collection;
}
//@! true: disable text editting. false: enable text editting;
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;//true下拉框不可编辑
}
}
具体效果入下:
折叠列表
要使 PropertyGrid 能够展开 SpellingOptions 属性,您需要创建 TypeConverter 。
TypeConverter 提供了从一种类型转换为另一种类型的方法。
PropertyGrid 使用 TypeConverter 将对象类型转换为 String ,并使用该 String 在网格中显示对象值。
在编辑过程中,TypeConverter 会将 String 转换回对象类型。
.NET 框架提供的 ExpandableObjectConverter 类可以简化这一过程。
private SpellingOptions _spellingOptions = new SpellingOptions();
[Category("折叠列表")]
[Browsable(true)]
public SpellingOptions SpellingOptions
{
get
{
return _spellingOptions;
}
set
{
_spellingOptions = value;
}
}
/// <summary>
/// 折叠列表元素
/// </summary>
[Description("展开查看应用程序的拼写选项")]
[TypeConverter(typeof(SpellingOptionsConverter))]
public class SpellingOptions
{
private bool isOne = true;
private bool isTwo = false;
private bool isThree = true;
[DefaultValue(true)]
public bool IsOne
{
get
{
return isOne;
}
set
{
isOne = value;
}
}
[DefaultValue(false)]
public bool IsTwo
{
get
{
return isTwo;
}
set
{
isTwo = value;
}
}
[DefaultValue(false)]
public bool IsThree
{
get
{
return isThree;
}
set
{
isThree = value;
}
}
}
/// <summary>
/// 自定义类型转换器
/// 所有继承TypeConverter必须实现的虚方法:
/// (1)CanConverterTo
/// (2)ConverterTo
/// </summary>
public class SpellingOptionsConverter: ExpandableObjectConverter
{
/// <summary>
/// 有一个Type参数(要转换成什么类型),例如要设计成转换成string,在方法体里面判断这个参数的Type如果是string,返回true,否则为false;
/// </summary>
/// <param name="context"></param>
/// <param name="destinationType"></param>
/// <returns></returns>
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(SpellingOptions))
{
return true;
}
return base.CanConvertTo(context, destinationType);
}
/// <summary>
/// 有Object参数和Type参数,将Object转换成Type类型的Object,返回Type类型的Object.
/// </summary>
/// <param name="context"></param>
/// <param name="culture"></param>
/// <param name="value"></param>
/// <param name="destinationType"></param>
/// <returns></returns>
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(System.String) &&
value is SpellingOptions)
{
SpellingOptions so = (SpellingOptions)value;
//返回字符串,显示选择结果
return "校验1:" + so.IsOne +
",校验2: " + so.IsTwo +
",校验3: " + so.IsThree;
}
return base.ConvertTo(context, culture, value, destinationType);
}
/// <summary>
/// 返回此转换器是否可以将一种类型的对象转换为此转换器的类型。例如string类型,如果是,返回true,否则返回false;
/// </summary>
/// <param name="context">提供格式上下文</param>
/// <param name="sourceType">表示要转换的类型</param>
/// <returns></returns>
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType==typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
}
具体效果如下:
下拉复选框
需创建一个新的组件,命名为CheckBoxEx,继承CheckedListBox类
[Editor(typeof(CheckBoxEditor), typeof(System.Drawing.Design.UITypeEditor))]
[Category("下拉复选")]
[Description("下拉复选")]
[Browsable(true)]
public string SchoolChoose { get; set; }
public class CheckBoxEditor : UITypeEditor
{
private CheckBoxEx check;
public CheckBoxEditor()
{
check = new CheckBoxEx();
check.BorderStyle = BorderStyle.None;
}
/// <summary>
/// 编辑值
/// </summary>
/// <param name="context">可用于获取附加上下文信息的 ITypeDescriptorContext。</param>
/// <param name="provider">一个 IServiceProvider ,此编辑器可用它来获取服务</param>
/// <param name="value">要编辑的对象。</param>
/// <returns>对象的新值。 如果尚未更改对象的值,则它返回的对象应与传递给它的对象相同。</returns>
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
if (context != null && context.Instance != null && provider != null)
{
IWindowsFormsEditorService service = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
if (service != null)
{
List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
if (check.DataSource == null)
{
list.Add(new KeyValuePair<string, string>("1", "清华"));
list.Add(new KeyValuePair<string, string>("2", "北大"));
list.Add(new KeyValuePair<string, string>("3", "人大"));
list.Add(new KeyValuePair<string, string>("4", "山大"));
}
check.DataSource = list;
// 在提供此服务的属性网格的值字段下方的下拉区域中显示指定控件。
service.DropDownControl(check);
return check.GetSelectItemValueText;
}
}
return null;
}
/// <summary>
/// 方法使用的编辑器样式,设置复选下拉框
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
//显示一个下拉箭头按钮,并在下拉对话框中承载用户界面
return UITypeEditorEditStyle.DropDown;
}
}
/// <summary>
/// 自定义复选框控件 继承CheckedListBox,设置复选框格式
/// </summary>
public partial class CheckBoxEx : CheckedListBox
{
public CheckBoxEx()
{
InitializeComponent();
}
public CheckBoxEx(IContainer container)
{
container.Add(this);
InitializeComponent();
}
public CheckItem Add(string code, string value)
{
CheckItem item = new CheckItem(code, value);
Items.Add(item);
return item;
}
public CheckItem Add(CheckItem item)
{
Items.Add(item);
return item;
}
#region 获取选择值
public string GetSelectItemValueText { get { return string.Join(",", GetSelectItemAll.Select(n => n.Value)); } }
public string GetSelectItemKeyText { get { return string.Join(",", GetSelectItemAll.Select(n => n.Key)); } }
public List<KeyValuePair<string, string>> GetSelectItemAll
{
get
{
List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
for (int i = 0; i < Items.Count; i++)
{
CheckItem item = Items[i] as CheckItem;
//返回指示指定项是否选中的值。如果选中该项,则为 true;否则为 false。
if (GetItemChecked(i))
{
list.Add(new KeyValuePair<string, string>(item.Code, item.Value));
}
}
return list;
}
}
#endregion
#region 绑定数据源
private object data;
public new object DataSource
{
get
{
return data;
}
set
{
data = value;
if (data is IEnumerable<KeyValuePair<string, string>>)
{
foreach (KeyValuePair<string, string> item in (data as IEnumerable<KeyValuePair<string, string>>))
{
Add(item.Key, item.Value);
}
}
else if (data is IEnumerable<CheckItem>)
{
foreach (var item in (data as IEnumerable<CheckItem>))
{
Add(item);
}
}
}
}
#endregion
}
具体效果如下:
弹窗
创建想要弹出的窗体
[Category("弹窗设置")]
[Description("弹窗")]
[Editor(typeof(PopUpEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(PopUpConverter))]
public string PopUp { get; set; }
public class PopUpEditor : UITypeEditor
{
private PopUpForm popUpForm;
/// <summary>
/// 设置编辑器样式
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
/// <summary>
/// 编辑指定对象的值
/// </summary>
/// <param name="context"></param>
/// <param name="provider"></param>
/// <param name="value"></param>
/// <returns></returns>
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
this.popUpForm = new PopUpForm();
IWindowsFormsEditorService conService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
conService.ShowDialog(this.popUpForm);
return value;
}
}
public class PopUpConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return true;
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
return string.Empty;
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return true;
}
}
具体效果如下: