الوصول إلى بيانات سياق إضافية في editvalue من uitypeeditor
-
23-09-2019 - |
سؤال
أنا أقوم بتبديل تطبيق 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
ستقوم العقار بإدراج جميع عناصر التحكم التي تتضمن النموذج وجميع أطفالها.