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

C# 接口上的只读属性在PropertyGrid中可编辑,c#,winforms,propertygrid,C#,Winforms,Propertygrid,我有一个带有一系列属性的接口,其中一些属性定义为只读,例如: public interface IActivity { string Id { get; } bool IsEnabled { get; } } 实现此接口的类具有公共set方法,可在其他地方使用,但此接口的使用者不应能够设置这些属性。我现在正在构建一个测试使用者,并通过PropertyGrid控件公开该对象。因为它使用公共集方法绑定到类,所以就使用者而言,只读的属性在网格中是可编辑的 我可以用两种方法解决这个问题,首先是

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

public interface IActivity {
  string Id { get; }
  bool IsEnabled { get; }
}
实现此接口的类具有公共
set
方法,可在其他地方使用,但此接口的使用者不应能够设置这些属性。我现在正在构建一个测试使用者,并通过PropertyGrid控件公开该对象。因为它使用公共集方法绑定到类,所以就使用者而言,只读的属性在网格中是可编辑的

我可以用两种方法解决这个问题,首先是将setters
设置为internal
,或者用
[ReadOnly]
属性标记属性,但是这似乎并不“正确”,因为理论上其他东西可能会在我的控制之外实现这个接口,使用那些假定为只读的属性,然后通过属性网格进行更改

将对象指定给属性网格时,我尝试显式强制转换到接口,但这也没有帮助:

propGrid.SelectedObject = (IActivity)obj;

有没有一种方法可以强制PropertyGrid控件遵守接口的约定,而不必更改具体类?

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

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

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

詹姆斯的答案是正确的。我只想补充一点,如果您的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生成这个包装。

网格可能使用反射来确定它应该显示哪些列,以及这些列是否可编辑。由于您要传递的对象属于允许编辑属性的类型,因此实际上您对此无能为力。将其强制转换为更受限制的类型不会有帮助,因为
SelectedObject
需要一个
object
。是的,这就是我所想的,考虑到可以应用其他属性来更改网格中的行为,它必须得到反映。我只是希望有一种方法可以迫使它遵循接口在我的情况下,它确实实现了
INotifyPropertyChanged
。我现在没有代码在我面前-我明天会回来看看我到底做了什么-我想这可能和你在这里看到的差不多。刚刚检查过-确实差不多,但是是在构造函数中用匿名lambda函数内联完成的。