2013-02-28 66 views
0

我想要定制一个属性,其中如果我点击elipses按钮[...]将会显示一个新的对话框窗体。不幸的是,表单不会显示。你可以请检查下面的代码,并告诉我哪里出错了?定制PropertyGrid控件

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; } 
     } 
    } 
} 

回答

1

你们的编辑与Foo工作类型(如果value不是Foo那么它不会显示对话框),但你创建的MyType一个实例,它包含string型,然后是一个财产Bar它可以”你的编辑FooEditor

来试试你的代码是如何运作的,你应该物业BarstringFoo改变:

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),但它改变了属性的FooValue价值

让我们再复杂类型介绍您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; 
    } 
} 

最后说明:在svc.ShowDialog()if块我们从更新值Form,属性Bar(应用编辑器)将不会更改,但我们将更新其包含的Foo实例的Value属性。大致相当于写的是这样的:

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工作
  • 主要来源PropertyDescriptor文档一直MSDN但here你可以找到一个非常简短的例子。
  • 如果你只需要本地化属性名称,你可以看看this entry here on SO