2010-03-29 3 views
4

WinForms 응용 프로그램을 조정 중입니다. 이 응용 프로그램에는 을 포함하는 Form이 있습니다. 개체는 SelectedObject 속성에 할당되므로 속성 표에 개체의 속성이 표시됩니다.UITypeEditor의 EditValue에서 추가 컨텍스트 데이터에 액세스

할당 된 개체의 유형은 을 지정하는 EditorAttribute을 포함하는 속성을가집니다.

이 구현은 UITypeEditorEditStyle.DropGetEditStyle 메서드로 재정 의하여 반환합니다. 해당 EditValue 메서드는 인스턴스 속성에 대한 값을 할당 할 수있는 ListBox을 표시합니다.

지금까지는 모든 것이 좋았습니다.

이제 PropertyGrid을 호스팅하는 Form에 의해 보유 된 다른 상태를 기반으로 목록의 사용 가능한 항목을 수정해야한다는 추가 요구 사항이 있습니다. 이 컨텍스트 정보를 EditValue 방법으로 가져 오는 방법을 알아낼 수 없습니다.

더 구체적인 유형으로 캐스팅을 시도해도 context 매개 변수에는 아무 것도없는 것 같습니다. provider에서 검색 할 다른 서비스를 추가하는 방법도 알아낼 수 없습니다.

아이디어가 있으십니까?

답변

2

당신이하려고하는 것이 TypeConverterGetStandardValues으로 더 좋을 것이라고 생각합니까? 그러나 어느 쪽이든, 모두 context.Instancecontext.PropertyDescriptor은 (모두 GetEditStyleEditValue에 대한) 빠른 테스트에 채워야 할을 보인다 다음 오버라이드 (override)에서

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() 
       } 
      } 
     }); 
    } 
} 
+0

덕분에, 나는 그리드의'SelectedObject' 속성에 할당 된 객체가 보관 유지하는 값을 __isn't__ _form_ 보유 값에 접근 할 필요가 . – AnthonyWJones

+0

@Anthony - 양식을 얻는 것이 까다로울 수 있습니다. 인스턴스로 추상화 할 수있는 방법이 있습니까? –

+1

나는 내가 할 수 있었다고 생각한다. 그러나 나는 다른 길이 있기를 바라고 있었다. 필자는 애플리케이션 아키텍처의 이익을 위해 객체를 운반하는 데이터를 오염시키고 싶지 않습니다. 추가 데이터에 액세스하는 다른 방법으로는 폼 자체 일 필요는 없습니다. 즉, IServiceProvider의 역할입니다.하지만이 컨텍스트에서 제공 할 서비스를 추가하는 방법을 찾을 수는 없습니다. – AnthonyWJones

1

:

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() 
       } 
      } 
     }); 
    } 
} 

또는 형식 컨버터 등

EditValue 메소드 context.Container은 편집기가 속한 오브젝트를 제공합니다. context.Container.Components 속성은 폼과 모든 자식을 포함하는 모든 컨트롤을 나열합니다.

4

나는 비슷한 상황에 있었고, 나는 커스텀 UITypeEditor의 생성자에 객체를 삽입하고 싶었다.

Nicolas Cadilhac의 설명에이어서 Here, HILL THE CREDIT. 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(); 
    } 
} 

마이클

마크는, 아마도 내 질문에 조정이 필요
관련 문제