2009-12-10 3 views
5

임의 객체의 속성을 편집 할 수있는 GUI 응용 프로그램을 작성하고 있습니다 (런타임에 해당 유형 만 알려짐).PropertyGrid 및 동적 객체 유형

이 기능을 사용하려면 PropertyGrid 컨트롤을 사용하기로 결정했습니다. 내가 편집해야하는 개체의 인스턴스를 얻을 때, 나는 그것을 위해 래퍼를 작성하고 선택한 개체로 설정

[TypeConverter(typeof(ExpandableObjectConverter))] 
[DefaultPropertyAttribute("Value")] 
public class Wrapper 
{ 
    public Wrapper(object val) 
    { 
     m_Value = val; 
    } 

    private object m_Value; 

    [NotifyParentPropertyAttribute(true)] 
    [TypeConverter(typeof(ExpandableObjectConverter))] 
    public object Value 
    { 
     get { return m_Value; } 
     set { m_Value = value; } 
    } 
} 

:

Wrapper wrap = new Wrapper(obj); 
propertyGrid.SelectedObject = wrap; 

하지만 나는 다음과 같은 클래스를 생성 '다음과 같은 문제가 발생합니다. obj 형식이 일부 사용자 지정 형식 (즉, 직접 정의한 클래스 또는 복잡한 형식으로 작성된 클래스) 인 경우에만 obj가 프리미티브 인 경우에만 위의 예상대로 작동합니다.

[TypeConverter(typeof(ExpandableObjectConverter))] 
public class SomeClass 
{ 
    public SomeClass() 
    { 
     a = 1; 
     b = 2; 
    } 

    public SomeClass(int a, int b) 
    { 
     this.a = a; 
     this.b = b; 
    } 

    private int a; 

    [NotifyParentPropertyAttribute(true)] 
    public int A 
    { 
     get { return a; } 
     set { a = value; } 
    } 

    private int b; 

    [NotifyParentPropertyAttribute(true)] 
    public int B 
    { 
     get { return b; } 
     set { b = value; } 
    } 
} 

을 그리고 수행합니다 : 예를 들어

, 나는 정의하면

Wrapper wrap = new Wrapper(new SomeClass()); 
propertyGrid.SelectedObject = wrap; 

그런 다음 모든 작업이 팽창.

int num = 1; 
Wrapper wrap = new Wrapper(num); 
propertyGrid.SelectedObject = wrap; 

가 그럼 난 그리드의 값을 "1"로 볼 수있다 (그리고 grayscaled 아니에요)하지만 난 값을 편집 할 수 없습니다 : 반면에, 때 나는 다음과 같은 수행합니다. Wrapper의 "Value"속성 유형을 int로 변경하고 TypeConverter 특성을 제거하면 작동하는 것으로 나타났습니다. 다른 기본 유형 및 문자열에 대해 동일한 동작이 발생합니다.

무엇이 문제입니까?

미리 감사드립니다.

답변

5

ExpandableObjectConverter를 Value 속성으로 설정하면 편집 할 수 없으며 CanConvertFrom이 false를 반환하기 때문에 정상입니다. 유형 변환기를 제거하면 PropertyGrid는 일반 TypeConverter를 사용하게되며 다시 동일한 경우가 발생합니다. 따라서 해결 방법은 올바른 TypeConverter에 대한 래퍼 역할을하는 더 똑똑한 TypeConverter를 부착하는 것입니다.

public class MySmartExpandableObjectConverter : ExpandableObjectConverter 
{ 
    TypeConverter actualConverter = null; 

    private void InitConverter(ITypeDescriptorContext context) 
    { 
     if (actualConverter == null) 
     { 
      TypeConverter parentConverter = TypeDescriptor.GetConverter(context.Instance); 
      PropertyDescriptorCollection coll = parentConverter.GetProperties(context.Instance); 
      PropertyDescriptor pd = coll[context.PropertyDescriptor.Name]; 

      if (pd.PropertyType == typeof(object)) 
       actualConverter = TypeDescriptor.GetConverter(pd.GetValue(context.Instance)); 
      else 
       actualConverter = this; 
     } 
    } 

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
    { 
     InitConverter(context); 

     return actualConverter.CanConvertFrom(context, sourceType); 
    } 

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
    { 
     InitConverter(context); // I guess it is not needed here 

     return actualConverter.ConvertFrom(context, culture, value); 
    } 
} 

은 당신이 뭔가를 세부적으로 조정해야하는 경우 알려줘 : 여기에 더러운 사람은 (내가 그냥은 ConvertFrom 부분을 구현하기 때문에 필요에 따라 당신이 그것을 완료,별로 시간을 보냈습니다)입니다.

니콜라스

+0

고마워, 그 속임수를 했어! :) – Marina

+0

왜이 줄은'parentConverter.GetProperties (context.Instance);'null을 반환합니까? –

0

속성 "값"에서 "TypeConverter"를 제거하면 propertygrid는 속성에있는 값의 typeo에서 "TypConverter"를 읽습니다.

+1

나는, 나는이 속성 그리드가 제대로 속성의 값을 표시 할 때, 그것을 시도하지만, 불행하게도 (obj가 원시적없는 경우에도이이 작업을 수행) – Marina

+0

그레이 스케일 및 편집이 비활성화 MS PropertyGrid는 Value 속성에 아무 변환기도 설정하지 않는 것이 현명하지 않습니다. 귀하의 int 들어, Int32Converter하지만 TypeConverter를 반환하지 않습니다. 내가 SPG에서이 사건을 처리해야했기 때문에 나는 그것을 안다. 해결 방법은 내 대답을 참조하십시오. –

+0

흠, 네 말이 맞아. 지금까지 나는 유죄 판결로 살았고, 그 재산 격자는 매우 영리합니다. 감사합니다 – TcKs