简体   繁体   中英

Possible to call the constructor of a WPF type editor (inheriting from ITypeEditor)?

In the answer to this question I am advised to use dependency injection in order to provide customization to a type editor which inherits from ITypeEditor (by "[passing something] into the constructor of your [type editor]" )

Since this type editor is just used to decorate the appropriate parameter, I do not know how to do this. I do not explicitly instantiate it, so I do not call its constructor.

I cannot find a solution/explanation to this online although I have found a statement relating to a similar situation (albeit with a UITypeEditor ) where it was said that "Since you don't create the instance of your own UITypeEditor derivative, you have no control over what arguments are passed to the constructor" . This is consistent with what I thought.

So, can I access the constructor to pass parameters into it, and if so how?

[Editor(typeof(MyControls.PropertyGridFilePicker), typeof(MyControls.PropertyGridFilePicker))]
public string ProjectFolder { get; set; } = "";

public partial class PropertyGridFilePicker : ITypeEditor
{
    
    public PropertyGridFilePicker()
    {
        InitializeComponent();

        // Constructor - if I could pass parameters into this it would of course be very useful

    }

    // The rest of the type editor methods go here

}

In your context Dependency Injection doesn't solve the problem. As you have noticed you have no control over the instance creation of your type. To allow Dependency Injection the API must support it eg, by accepting an abstract factory as parameter.

To solve your problem, you should create an abstract base type which encapsulates the common behavior of all your editors. Using specializations is also more maintainable, than adding configuration parameters to control/extend behavior. Given your posted code I assume you want to execute a specialized action when the browse button was pressed. You should delegate this behavior to subclasses by implementing this behavior as abstract in your base type. Then simply use the types of the specialed classes as parameter for the EditorAttribute :

PropertyGridBrowser.cs

// The abstract common base class. Override 'ExecuteBrowse' to extend behavior.
public abstract class PropertyGridBrowser : UserControl, ITypeEditor
{
    public string Value
    {
        get { return (string)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(string), typeof(PropertyGridFilePicker), new PropertyMetadata(null));

    protected PropertyGridBrowser()
    {
        InitializeComponent();
    }   

    public FrameworkElement ResolveEditor(PropertyItem propertyItem)
    {
        Binding binding = new Binding("Value");
        binding.Source = propertyItem;
        binding.Mode = propertyItem.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay;
        BindingOperations.SetBinding(this, ValueProperty, binding);
        return this;
    }

    protected abstract void ExecuteBrowse();

    private void PickFileButton_Click(object sender, RoutedEventArgs e)
    {
        ExecuteBrowse();
    }
}

PropertyGridFilePicker.cs

public partial class PropertyGridFilePicker : PropertyGridBrowser
{
    string rtn = "";
    public PropertyGridFilePicker() : base()
    {
    }

    protected override void ExecuteBrowse()
    {
        OpenFileDialog fd = new OpenFileDialog();
        if (fd.ShowDialog() == true && fd.CheckFileExists)
        {
            Value = fd.FileName;
        }
    }
}

PropertyGridFolderPicker.cs

public partial class PropertyGridFolderPicker : PropertyGridBrowser
{
    public PropertyGridFilePicker() : base()
    {
    }

    protected override void ExecuteBrowse()
    {
        var dialog = new System.Windows.Forms.FolderBrowserDialog();
        System.Windows.Forms.DialogResult result = dialog.ShowDialog();

        if (result == System.Windows.Forms.DialogResult.OK)
        {
            
        }
    }
}

Example

// Use a file browser
[Editor(typeof(MyControls.PropertyGridFilePicker), typeof(MyControls.PropertyGridFilePicker))]
public string ProjectFolder { get; set; } = "";

// Use a folder browser
[Editor(typeof(MyControls.PropertyGridFolderPicker), typeof(MyControls.PropertyGridFolderPicker))]
public string ProjectFolder { get; set; } = "";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM