简体   繁体   English

可以调用 WPF 类型编辑器的构造函数(从 ITypeEditor 继承)?

[英]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]" )在回答这个问题时,建议我使用依赖注入来为从ITypeEditor继承的类型编辑器提供自定义(通过“[将某些内容] 传递到 [类型编辑器] 的构造函数中”

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" .尽管我找到了与类似情况有关的声明(尽管使用UITypeEditor ),但我在网上找不到解决方案/解释, 据说“由于您没有创建自己的UITypeEditor衍生的实例,因此您没有控制将 arguments 传递给构造函数的内容” 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.为了允许依赖注入,API 必须支持它,例如,通过接受抽象工厂作为参数。

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 :然后只需使用特殊类的类型作为EditorAttribute的参数:

PropertyGridBrowser.cs 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 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 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; } = "";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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