반응형
public delegate object DynamicGetValue<T>(T component);
public delegate void DynamicSetValue<T>(T component, object newValue);

public class DynamicPropertyDescriptor<T> : PropertyDescriptor
    where T: class
{
    public enum AccessMode
    {
        ReadWrite,
        ReadOnly,
    };
    
    protected Type _componentType;
    protected Type _propertyType;
    protected DynamicGetValue<T> _getDelegate;
    protected DynamicSetValue<T> _setDelegate;

    public override string DisplayName
    {
        get
        {
            return base.DisplayName;
        }
    }
    
    public DynamicPropertyDescriptor(string name, Type propertyType,
        DynamicGetValue<T> getDelegate, DynamicSetValue<T> setDelegate, Attribute[] attrs = null)
        :
        base(name, attrs)
    {
        _componentType = typeof(T);
        _propertyType = propertyType;
        _getDelegate = getDelegate;
        _setDelegate = setDelegate;
    }
    public DynamicPropertyDescriptor(string name, Type propertyType, AccessMode accessMode = AccessMode.ReadWrite,  Attribute[] attrs = null)
        : base(name, attrs)
    {
        _componentType = typeof(T);
        _propertyType = propertyType;

        _getDelegate += component => _componentType.GetProperty(name).GetValue(component, null);
        if(accessMode==AccessMode.ReadWrite)
            _setDelegate += (component, value) => _componentType.GetProperty(name).SetValue(component, value, null);
    }

    public override bool CanResetValue(object component)
    {
        return false;
    }
        public override Type ComponentType
    {
        get { return _componentType; }
    }

    public override object GetValue(object component)
    {
        return _getDelegate(component as T);
    }

    public override bool IsReadOnly
    {
        get { return _setDelegate == null; }
    }

    public override Type PropertyType
    {
        get { return _propertyType; }
    }

    public override void ResetValue(object component)
    {
        
    }

    public override void SetValue(object component, object value)
    {
        _setDelegate(component as T, value);
    }

    public override bool ShouldSerializeValue(object component)
    {
        return true;
    }
}
    
//위에 클래스가 Dynamic하게 동적으로 PropetyGrid에 Binding하기위한 클래스 이다.
//실제 PropertyGrid에 어떤 이벤트에서 처리를 하냐면

PropertyGrid.CustomPropertyDescriptors += PropertyGrid_CustomPropertyDescriptors;

//이벤트 등록을 완료한 후


 private void _propertyGrid_CustomPropertyDescriptors(object sender, DevExpress.XtraVerticalGrid.Events.CustomPropertyDescriptorsEventArgs e)
 {
     if (e.Source != null)
     {
         e.Properties = new PropertyDescriptorCollection(_propertyDescriptors.ToArray());
     }
 }



//이제 거의 끝났다.. 그렇다면 _propertyDescriptors 는 어떻게 생성할까?
//내경우는 실제 바인딩 객체(=> PropertyGrid.Selectobject 에 Dictionary를 넣었기 때문에 아래와 같이 코딩이 되었다.)

List<DynamicPropertyDescriptor> _propertyDescriptors = new List<DynamicPropertyDescriptor>();

var dynamicPropertyDes = new DynamicPropertyDescriptor<MyType>(
    displayName //속성창에 이름
    , typeof(string) //값의 타입
    , dic => dic.ContainsKey(value.ToString()) ? dic[value.ToString()] : string.Empty // 실제 바인딩된 객체의 Getter
    , (dic, input) =>{dic[value.ToString()] = input.ToString().Trim();}                     //실제 바인딩된 객체의 Setter
    , new []{new CategoryAttribute("Category"), }                                           //Category셋팅
    );

_propertyDescriptors.Add(dynamicPropertyDes);


//이렇게 코딩을 하면 원하는 값과 형태로 PropertyGrid에 동적으로 할당할 수 있을 것이다.

+ Recent posts