你可以为你的实体编写一个包装,实现ICustomTypeDescriptor
。这样,你可以决定哪些属性是只读或不是......但对于一个不那么复杂的场景来说这是相当多的工作。
更简单的解决方案是,当您希望该属性为只读属性时,将绑定的DataSourceUpdateMode
更改为Never
。
更新:这是实现ICustomTypeDescriptor
一个基本的包装:
class EntityWrapper<T> : CustomTypeDescriptor
{
public EntityWrapper(T entity)
{
this.Entity = entity;
var properties = TypeDescriptor.GetProperties(typeof(T))
.Cast<PropertyDescriptor>()
.ToArray();
ReadOnly = properties.ToDictionary(p => p.Name, p => p.IsReadOnly);
_properties = new PropertyDescriptorCollection(properties
.Select(p => new WrapperPropertyDescriptor(p, this))
.ToArray());
}
public T Entity { get; private set; }
public Dictionary<string, bool> ReadOnly { get; private set; }
public override PropertyDescriptorCollection GetProperties()
{
return _properties;
}
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return _properties;
}
private PropertyDescriptorCollection _properties;
private class WrapperPropertyDescriptor : PropertyDescriptor
{
private EntityWrapper<T> _entityWrapper;
private PropertyDescriptor _property;
public WrapperPropertyDescriptor(PropertyDescriptor property, EntityWrapper<T> entityWrapper)
: base(property)
{
_property = property;
_entityWrapper = entityWrapper;
}
public override bool CanResetValue(object component)
{
return _property.CanResetValue(component);
}
public override Type ComponentType
{
get { return _property.ComponentType; }
}
public override object GetValue(object component)
{
return _property.GetValue(component);
}
public override bool IsReadOnly
{
get
{
return _entityWrapper.ReadOnly[this.Name];
}
}
public override Type PropertyType
{
get { return _property.PropertyType; }
}
public override void ResetValue(object component)
{
_property.ResetValue(component);
}
public override void SetValue(object component, object value)
{
_property.SetValue(component, value);
}
public override bool ShouldSerializeValue(object component)
{
return _property.ShouldSerializeValue(component);
}
}
}
正如你所看到的,这是完全可能使属性只读只是一个实例:
MyEntity a = new MyEntity { Foo = "hello", Bar = 42 };
MyEntity b = new MyEntity { Foo = "world", Bar = 5 };
EntityWrapper<MyEntity> wa = new EntityWrapper<MyEntity>(a);
EntityWrapper<MyEntity> wb = new EntityWrapper<MyEntity>(b);
var fooA = wa.GetProperties()["Foo"];
var fooB = wb.GetProperties()["Foo"];
wa.ReadOnly["Foo"] = false;
wb.ReadOnly["Foo"] = true;
Console.WriteLine("Property Foo of object a is read-only : {0}", fooA.IsReadOnly);
Console.WriteLine("Property Foo of object b is read-only : {0}", fooB.IsReadOnly);
嘿请注意,每个属性都具有不同的只读逻辑。你将如何包装域对象来启用它? 关于将相同的数据源绑定到许多控件上的性能问题呢? – 2010-03-16 19:46:05