سؤال

أنا أقوم بتبديل تطبيق WinForms. يحتوي هذا التطبيق على ملف Form الذي يحتوي على أ PropertyGrid. يتم تعيين كائن إلى SelectedObject الخاصية بحيث تعرض شبكة الخصائص خصائص الكائن.

يحتوي نوع الكائن المعين على خاصية تحمل EditorAttribute تحديد أ UITypeEditor.

هذا تنفيذ UITypeEditor عائدات UITypeEditorEditStyle.Drop في تجاوزه GetEditStyle طريقة. انها EditValue تعرض الطريقة أ ListBox التي يمكن تعيين قيمة لخاصية المثيل.

كل شيء جيد حتى الآن.

الآن لدي شرط إضافي يدعو إلى تعديل العناصر المتاحة في القائمة بناءً على حالة أخرى تحتفظ بها Form استضافة PropertyGrid. لا يمكنني معرفة كيفية الحصول على هذه المعلومات السياقية إلى EditValue طريقة.

لا يبدو أن هناك أي شيء على context المعلمة حتى لو حاولت إلقاءها على أنواع أكثر تحديدًا. لا يمكنني معرفة كيفية إضافة بعض الخدمات الأخرى لاستردادها من provider.

أيه أفكار؟

هل كانت مفيدة؟

المحلول

أتساءل ما إذا كان ما تحاول فعله سيكون أفضل كما TypeConverter عبر GetStandardValues؟ لكن في كلتا الحالتين ، كلاهما context.Instance و context.PropertyDescriptor يبدو أن يتم ملؤها في اختبار سريع (لكليهما GetEditStyle و EditValue):

using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
class MyData
{
    [Editor(typeof(MyEditor), typeof(UITypeEditor))]
    public string Bar { get; set; }

    public string[] Options { get; set; }
}
class MyEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        // break point here; inspect context
        return UITypeEditorEditStyle.DropDown;
    }
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        // break point here; inspect context
        return base.EditValue(context, provider, value);
    }

}
class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form
        {
            Controls =
            {
                new PropertyGrid {
                    Dock = DockStyle.Fill,
                    SelectedObject = new MyData()
                }
            }
        });
    }
}

أو كمحرك نوع:

using System;
using System.ComponentModel;
using System.Windows.Forms;

class MyData
{
    [TypeConverter(typeof(MyConverter))]
    public string Bar { get; set; }

    public string[] Options { get; set; }
}
class MyConverter : StringConverter
{
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }
    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        MyData data = (MyData)context.Instance;
        if(data == null || data.Options == null) {
            return new StandardValuesCollection(new string[0]);
        }
        return new StandardValuesCollection(data.Options);
    }
}
class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form
        {
            Controls =
            {
                new PropertyGrid {
                    Dock = DockStyle.Fill,
                    SelectedObject = new MyData()
                }
            }
        });
    }
}

نصائح أخرى

كنت في وضع مماثل ، أردت حقن كائن في مُنشئ UityPeeditor المخصص.

تابعت تعليق نيكولاس كاديلهاك في هنا, ، أعطه كل الفضل. ويستخدم typedescriptionProvider.

هنا هي المجموعة الكاملة من التعليمات البرمجية.

class Foo
{
    public Foo() { Bar = new Bar(); }
    public Bar Bar { get; set; }
}

class Bar
{
    public string Value { get; set; }
}

class BarTypeDescriptionProvider : TypeDescriptionProvider
{
    private TypeDescriptionProvider _baseProvider;
    string _extraParam;

    public BarTypeDescriptionProvider(Type t, string extraParam)
    {
        this._extraParam = extraParam;
        _baseProvider = TypeDescriptor.GetProvider(t);
    }

    public string ExtraParam
    { 
        get { return _extraParam; } 
    }

    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
    {
        return new BarTypeDescriptor(this, _baseProvider.GetTypeDescriptor(objectType, instance), objectType);
    }
}


class BarTypeDescriptor : CustomTypeDescriptor
{
    private Type _objectType;
    private BarTypeDescriptionProvider _provider;

    public BarTypeDescriptor(BarTypeDescriptionProvider provider,  ICustomTypeDescriptor descriptor, Type objectType): base(descriptor)
    {
        if (provider == null) throw new ArgumentNullException("provider");
        if (descriptor == null)
            throw new ArgumentNullException("descriptor");
        if (objectType == null)
            throw new ArgumentNullException("objectType");
        _objectType = objectType;
        _provider = provider;
    }

    public override object GetEditor(Type editorBaseType)
    {
        return new BarEditor(_provider.ExtraParam);
    }
}


class BarEditor : UITypeEditor
{
    private string _extraParam;
    public BarEditor(string x)
        : base()
    {
        _extraParam = x;
    }

    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.Modal;
    }
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        MessageBox.Show(_extraParam);
        return base.EditValue(context, provider, value);
    }
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        string extraParam = "Extra param from main form";

        TypeDescriptor.AddProvider(new BarTypeDescriptionProvider(typeof(Bar), extraParam), typeof(Bar));

        this.propertyGrid1.SelectedObject = new Foo();
    }
}

ميخائيل

في طريقة EditValue المتجاوز ، context.Container سيوفر الكائن الذي ينتمي إليه المحرر. ال context.Container.Components ستقوم العقار بإدراج جميع عناصر التحكم التي تتضمن النموذج وجميع أطفالها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top