我正在尝试自定义一个属性,如果我单击elipses按钮[...],将显示一个新的对话框表单。不幸的是,表格不会显示。您能否查看以下代码并告知我哪里出错了?
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System;
namespace Test01
{
/// <summary>
/// Description of MainForm.
/// </summary>
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
void MainFormLoad(object sender, EventArgs e)
{
Form form = new Form();
propertyGrid1.SelectedObject = new MyType();
}
}
class MyType
{
private string bar;
[Editor(typeof(FooEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(ExpandableObjectConverter))]
public string Bar
{
get { return bar; }
set { bar = value; }
}
}
[Editor(typeof(FooEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(ExpandableObjectConverter))]
class Foo
{
private string bar;
public string Bar
{
get { return bar; }
set { bar = value; }
}
}
class FooEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, System.IServiceProvider provider, object value)
{
IWindowsFormsEditorService svc = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
Foo foo = value as Foo;
if (svc != null && foo != null)
{
using (FooForm form = new FooForm())
{
form.Value = foo.Bar;
if (svc.ShowDialog(form) == DialogResult.OK)
{
foo.Bar = form.Value; // update object
}
}
}
return value; // can also replace the wrapper object here
}
}
class FooForm : Form
{
private TextBox textbox;
private Button okButton;
public FooForm()
{
textbox = new TextBox();
Controls.Add(textbox);
okButton = new Button();
okButton.Text = "OK";
okButton.Dock = DockStyle.Bottom;
okButton.DialogResult = DialogResult.OK;
Controls.Add(okButton);
}
public string Value
{
get { return textbox.Text; }
set { textbox.Text = value; }
}
}
}
答案 0 :(得分:3)
您的编辑器使用Foo
类型(如果value
不是Foo
,那么它不会显示对话框),但您创建了MyType
的实例,它包含一个Bar
类型的string
属性,但您的FooEditor
无法对其进行编辑。
要尝试代码的工作方式,您应该将属性Bar
从string
更改为Foo
:
class MyType
{
private Foo bar = new Foo();
[Editor(typeof(FooEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(ExpandableObjectConverter))]
public Foo Bar
{
get { return bar; }
set { bar = value; }
}
}
<强>实施例强>
我们来看两个例子。在第一个编辑已应用Attribute
的属性(然后编辑器更改属性本身的值):
这是您要在PropertyGrid
中修改的课程,我删除了Foo
课程,因为此示例无效:
class MyType
{
private string bar;
[Editor(typeof(MyStringEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(ExpandableObjectConverter))]
public string Bar
{
get { return bar; }
set { bar = value; }
}
}
这是将编辑您的Bar
媒体资源的编辑器。实际上它适用于string
类型的任何属性:
class MyStringEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
var svc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
string text = value as string;
if (svc != null && text != null)
{
using (FooForm form = new FooForm())
{
form.Value = text;
if (svc.ShowDialog(form) == DialogResult.OK)
{
return form.Value;
}
}
}
return value;
}
}
现在的另一个例子,编辑器不会更改属性值本身,而是更改该属性的属性值(编辑器应用于属性MyType.Bar
(类型为Foo
)但它会更改Value
的属性Foo
的值。
让我们再次为您的Bar
属性引入一个复杂类型:
class Foo
{
private string _value;
private object _tag; // Unused in this example
public string Value
{
get { return _value; }
set { _value = value; }
}
public object Tag
{
get { return _tag; }
set { _value = _tag; }
}
}
更改MyType
类以发布我们编写的复杂类型的一个属性,请注意EditorAttribute
现在使用特定于Foo
类型的新编辑器:
class MyType
{
private Foo bar = new Foo();
[Editor(typeof(FooEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(ExpandableObjectConverter))]
public Foo Bar
{
get { return bar; }
set { bar = value; }
}
}
最后,我们编写了Foo
类型的编辑器。请注意,此编辑器仅更改属性Foo.Value
的值,Foo
公开的其他属性将不会被触及:
class FooEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
var svc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
Foo foo = value as Foo;
if (svc != null && foo != null)
{
using (FooForm form = new FooForm())
{
form.Value = foo.Value;
if (svc.ShowDialog(form) == DialogResult.OK)
{
// Updates the value of the property Value
// of the property we're editing.
foo.Value = form.Value;
}
}
}
// In this case we simply return the original property
// value, the property itself hasn't been changed because
// we updated the value of an inner property
return value;
}
}
最后提示:在if
的{{1}}区块中,我们拥有svc.ShowDialog()
的更新值,属性Form
(应用编辑器的位置)不会被更改但我们将更新它包含的Bar
实例的Value
属性。大致相当于写这样的东西:
Foo
如果我们只为属性返回一个新值(如上例所示),MyType myType = new MyType();
myType.Bar.Value = form.Value;
属性的旧值将丢失,如下所示:
Tag
你能看出区别吗?无论如何,这将是一个教程而不是答案......
请注意,示例未经测试,我只是在这里写,我只是想揭示这个概念,而不是提供一个确实有效的例子。
<强>参考强>
在这里您可以找到有用资源的简短列表:
MyType myType = new MyType();
Foo foo = new Foo();
foo.Value = form.Value;
myType.Bar = foo;
如何运作的comprehensive example UITypeEditor
文档的主要来源始终是MSDN,here您可以找到一个非常简短的示例。