我的表单上有一个 PropertyGrid。我的老板认为这很丑陋。粗野。朴实无华。
他想要一个漂亮、整洁、干净的表格。这里有一个问题:其中一个属性是我们自产的对象的集合。他喜欢这个集合的集合编辑器。
我知道我可以建立自己的收藏编辑器。但是有没有一个干净、简单的解决方案来节省我几个小时的编码时间,这样我就可以直接创建和使用集合编辑器而不使用属性网格?
我的表单上有一个 PropertyGrid。我的老板认为这很丑陋。粗野。朴实无华。
他想要一个漂亮、整洁、干净的表格。这里有一个问题:其中一个属性是我们自产的对象的集合。他喜欢这个集合的集合编辑器。
我知道我可以建立自己的收藏编辑器。但是有没有一个干净、简单的解决方案来节省我几个小时的编码时间,这样我就可以直接创建和使用集合编辑器而不使用属性网格?
您可以从UITypeEditor
(via TypeDescriptor
) 获得此功能,但这并非易事 - 您需要设置 an IServiceProvider
、 an IWindowsFormsEditorService
,理想情况下是 an ITypeDescriptorContext
- 相当麻烦。如果您不熟悉这些工具,手动操作可能会更简单。
或者,看看SmartPropertyGrid.NET,它是PropertyGrid
.
更新:这是一个工作示例......绝对不是微不足道的,但随意窃取代码。它仅适用于模态编辑器,不适用于下拉菜单。它也不是“关注点分离”的一个很好的例子。这MyHelper
堂课很有趣。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
class Foo
{
public Foo() { Bars = new List<Bar>(); }
public List<Bar> Bars { get; private set; }
}
class Bar
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
static class Program
{
[STAThread]
static void Main()
{
Foo foo = new Foo();
Bar bar = new Bar();
bar.Name = "Fred";
bar.DateOfBirth = DateTime.Today;
foo.Bars.Add(bar);
Application.EnableVisualStyles();
using(Form form = new Form())
using (Button btn = new Button())
{
form.Controls.Add(btn);
btn.Text = "Edit";
btn.Click += delegate
{
MyHelper.EditValue(form, foo, "Bars");
};
Application.Run(form);
}
}
}
class MyHelper : IWindowsFormsEditorService, IServiceProvider, ITypeDescriptorContext
{
public static void EditValue(IWin32Window owner, object component, string propertyName) {
PropertyDescriptor prop = TypeDescriptor.GetProperties(component)[propertyName];
if(prop == null) throw new ArgumentException("propertyName");
UITypeEditor editor = (UITypeEditor) prop.GetEditor(typeof(UITypeEditor));
MyHelper ctx = new MyHelper(owner, component, prop);
if(editor != null && editor.GetEditStyle(ctx) == UITypeEditorEditStyle.Modal)
{
object value = prop.GetValue(component);
value = editor.EditValue(ctx, ctx, value);
if (!prop.IsReadOnly)
{
prop.SetValue(component, value);
}
}
}
private readonly IWin32Window owner;
private readonly object component;
private readonly PropertyDescriptor property;
private MyHelper(IWin32Window owner, object component, PropertyDescriptor property)
{
this.owner = owner;
this.component = component;
this.property = property;
}
#region IWindowsFormsEditorService Members
public void CloseDropDown()
{
throw new NotImplementedException();
}
public void DropDownControl(System.Windows.Forms.Control control)
{
throw new NotImplementedException();
}
public System.Windows.Forms.DialogResult ShowDialog(System.Windows.Forms.Form dialog)
{
return dialog.ShowDialog(owner);
}
#endregion
#region IServiceProvider Members
public object GetService(Type serviceType)
{
return serviceType == typeof(IWindowsFormsEditorService) ? this : null;
}
#endregion
#region ITypeDescriptorContext Members
IContainer ITypeDescriptorContext.Container
{
get { return null; }
}
object ITypeDescriptorContext.Instance
{
get { return component; }
}
void ITypeDescriptorContext.OnComponentChanged()
{}
bool ITypeDescriptorContext.OnComponentChanging()
{
return true;
}
PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor
{
get { return property; }
}
#endregion
}