接口上的只读属性可在PropertyGrid中编辑

时间:2015-03-09 10:48:30

标签: c# winforms propertygrid

我有一个带有一堆属性的接口,其中一些被定义为只读,例如:

public interface IActivity {
  string Id { get; }
  bool IsEnabled { get; }
}

实现此接口的类具有公共set方法,以供在其他地方使用,但此接口的使用者不应该能够设置这些属性。我现在正在构建一个测试使用者,并通过PropertyGrid控件公开该对象。因为它使用公共集合方法绑定到类,所以对于消费者应该关注的属性是可在网格内编辑的。

我可以通过两种方式解决此问题,首先是制作setter internal,或者使用[ReadOnly]属性标记属性,但这似乎并不“正确”,因为理论上其他东西可以实现我的控制之外的那个接口,那些所谓的只读属性然后可以通过属性网格更改。

我在将对象分配给属性网格时尝试显式转换为接口,但这也没有帮助:

propGrid.SelectedObject = (IActivity)obj;

有没有办法强制PropertyGrid控件尊重接口的合约,而不是必须更改具体的类?

2 个答案:

答案 0 :(得分:1)

我通过创建一个与接口规范完全匹配的包装类来解决这个问题:

class ActivityWrapper : IActivity {
    private readonly IActivity _activity;
    public ActivityWrapper(IActivity activity) {
        _activity = activity;
    }

    public string Id
    {
        get { return _activity.Id; }
    }
    public bool IsEnabled
    {
        get { return _activity.IsEnabled; }
    }
}

在将对象暴露给属性网格时使用它:

propGrid.SelectedObject = new ActivityWrapper((IActivity)obj);

如果有一种不同的,更自动的方法来实现这一点,我仍然感兴趣,而不是维持另一个班级。

答案 1 :(得分:1)

詹姆斯的回答是正确的。我将补充一点,如果你的IActivity实现了INotifyPropertyChanged,你必须以这样的方式路由事件:

class ActivityWrapper : IActivity
{
    private readonly IActivity _activity;
    public ActivityWrapper(IActivity activity)
    {
        _activity = activity;
        _activity.PropertyChanged += _activity_PropertyChanged;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    void _activity_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, e);
    }

    public string Id
    {
        get { return _activity.Id; }
    }
    public bool IsEnabled
    {
        get { return _activity.IsEnabled; }
    }
}

我认为自动执行此操作的唯一方法是使用Reflection.Emit生成此包装器。