Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
989 views
in Technique[技术] by (71.8m points)

.net - C# UITypeEditor with Parameter

I have created a custom UITypeEditor which launches a form (StringSelector) to display a list of strings which the user choses from. The problem is that this form needs to know what StringManager to use (stringmanage is simply a class which contains all the strings allowed in a List).

When I created this form I was passing in the StringManager as a parameter in the Constructor, but I cannot work out how i can do this with the UITypeEditor.

Below is my current code which uses a constructor which has no parameters, just to get the form to show, however there are obviously no strings as I didn't call the parameter version of the constructor.

How can I pass a parameter to the UITypeEditor which I can then use within the EditValue function? Many thanks.

class StringSelectorEditor : 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;

        StringItem item = value as StringItem;

        if (svc != null)
        {
            // ###### How do I pass a reference to this EditValue function so that I can....
            using (StringSelector form = new StringSelector(/* ... INSERT IT HERE */))
            {
                form.Value = item;
                if (svc.ShowDialog(form) == DialogResult.OK)
                {
                    item = form.Value; // update object
                }
            }
        }
        return value; // can also replace the wrapper object here
    }
}

UPDATED with additional detail: As requested, I have a class called ControlInstance which itself contains the populated StringManager. It is this ControlInstance Class which is passed to the PropertyGrid control and its accessor functions displayed in it including the above described StringSelectorEditor UITypeEditor reference. Here is a snippet of the code:

public class ControlInstance_Label : ControlInstance
{
    StringManager stringManager;
    string thisName = "";
    StringItem linkedStringItem;

    public ControlInstance_Label(String TextFilePath) 
    {
        // Code here which populates the StringManager with text from the above file
    }

    [Category("Design"), Description("Control Name")]
        public String Name
        {
            get { return thisName; }
            set { thisName = value; }
        }

    // THIS IS WERE I SOMEHOW NEED TO PASS IN THE StringManager Ref to the EditValue function of the custom UITypeEditor
    [Category("Design"), Description("Static String Linked to this Control")]
        [Editor(typeof(StringSelectorEditor), typeof(UITypeEditor))]
        public StringItem LinkedString
        {
            get { return linkedStringItem; }
            set { linkedStringItem = value; }
        }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

EditValue method has a context parameter which is of type ITypeDescriptorContext and has an Instance property which is the owner object of the property that you are editing.

So you can have access to any public properties in your class by simply casting context.Instance to the owner class type. Also you can use reflection to have access to private members as well.

Example

Here is a class that accepts a List<string> in its constructor and I'm going to use those values when editing SomeValue property. To do so, I store the passed list in an invisible property SomeList and will use it in EditValue of my custom UI type editor. You can keep the list in a private property if you like and then extract values using reflection. Here is a simple MyClass implementation:

public class MyClass
{
    [Browsable(false)]
    public List<String> SomeList { get; set; }
    public MyClass(List<String> list)
    {
        SomeList = list;
    }

    [Editor(typeof(MyUITypeEditor), typeof(UITypeEditor))]
    public string SomeValue { get; set; }
}

Here in MyUITypeEditor in EditValue method, I extract list values from context.Instance which is the instance of the object which we are editing its property. Then just for example I show extracted values in a message box:

public class MyUITypeEditor : UITypeEditor
{
    public override object EditValue(ITypeDescriptorContext context, 
        IServiceProvider provider, object value)
    {
        //Just as an example, show a message box containing values from owner object
        var list = ((MyClass)context.Instance).SomeList;
        MessageBox.Show(string.Format("You can choose from {0}.",
            string.Join(",", list)));

        return base.EditValue(context, provider, value);
    }
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.Modal;
    }
}

To test it, it's enough to show an instance of MyClass in a property grid and try to edit SomeValue property in property grid:

var myObject = new MyClass(new List<string>() { "A", "B", "C" });
this.propertyGrid1.SelectedObject = myObject;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...