PropertyGrid没有注意到代码中的属性发生了变化?

时间:2012-04-10 15:56:47

标签: c# winforms data-binding inotifypropertychanged propertygrid

我有一个Winform应用程序,它使用颜色突出显示某些内容。我想让用户改变'他们'的颜色。作为练习,我想我会创建一个类的实例,其中包含颜色属性,并将其分配给属性网格(以获得一个漂亮的编辑器)

这似乎工作正常,但我认为我想让用户重置颜色(在他们摆弄并将它们设置为20种米色色调之后)。所以,我在表单中添加了一个“重置”按钮,它将我的对象的颜色属性设置回默认值。

然而,似乎在重新设置对象的属性时,属性网格不会改变。如果在重置后,我执行属性网格“刷新”,则它具有重置颜色。

我假设属性网格不知道底层对象已被更改?

这个场景中是否缺少某些内容,或者我应该接受它并在重置对象时调用Refresh方法?

由于

(非常相似的问题here

public partial class Form1 : Form
{
  public Form1()
  {
     InitializeComponent();

     this.propertyGrid1.SelectedObject = new Colours();
  }

  private void button1_Click(object sender, EventArgs e)
  {
     Colours colours = this.propertyGrid1.SelectedObject as Colours;
     colours.Reset();
  }
}

public partial class Colours : INotifyPropertyChanged 
{
  public event PropertyChangedEventHandler PropertyChanged;

  public Color ColourP1 { get; set; }

  public void Reset()
  {
     this.ColourP1 = Color.Red;
     var handler = this.PropertyChanged;
     if (handler != null) handler(this, new PropertyChangedEventArgs("ColourP1"));
  }
}

继续我对的评论“没有订阅INotifyPropertyChanged.PropertyChanged”之后,对PropertyGrid控件进行子类化的缺点是什么呢?

public partial class MyPropertyGrid : System.Windows.Forms.PropertyGrid
{
  private INotifyPropertyChanged _selectedObject;

  protected override void OnSelectedObjectsChanged(EventArgs e)
  {
     base.OnSelectedObjectsChanged(e);

     if (_selectedObject != null) _selectedObject.PropertyChanged -= selectedObject_PropertyChanged;
     _selectedObject = this.SelectedObject as INotifyPropertyChanged;
     if (_selectedObject != null) _selectedObject.PropertyChanged += selectedObject_PropertyChanged;
  }

  private void selectedObject_PropertyChanged(object sender, PropertyChangedEventArgs e)
  {
     this.Refresh();
  }
}

4 个答案:

答案 0 :(得分:11)

要回答有关PropertyGrid未更改的原因的问题,PropertyGrid的MSDN文档说明了这一点:

  

网格中显示的信息是属性的快照   在分配对象时。如果是对象的属性值   由SelectedObject指定的代码在运行时更改   在网格中执行操作之前,不会显示新值   导致网格刷新。

因此,似乎PropertyGrid不是可自动更新的控件。我认为这样的线索是PropertyGrid使用SelectedObject方法而不是DataSource方法,而后者意味着它可能会监听INotifyPropertyChanged。

你留下LarsTech的建议并手动刷新网格。

答案 1 :(得分:8)

尝试刷新它:

private void button1_Click(object sender, EventArgs e)
{
  Colours colours = this.propertyGrid1.SelectedObject as Colours;
  colours.Reset();
  this.propertyGrid1.Refresh();
}

假设您有更多属性,可以使用PropertyChanged事件。我会像这样修改你的Color类:

public class Colours : INotifyPropertyChanged {
  public event PropertyChangedEventHandler PropertyChanged;

  private Color _ColourP1;

  public void Reset() {
    this.ColourP1 = Color.Red;
  }

  private void OnChanged(string propName) {
    if (PropertyChanged != null)
      PropertyChanged(this, new PropertyChangedEventArgs(propName));
  }

  public Color ColourP1 {
    get { return _ColourP1; }
    set {
      _ColourP1 = value;
      OnChanged("ColourP1");
    }
  }
}

然后你的表格看起来像这样:

public Form1() {
  InitializeComponent();

  Colours colours = new Colours();
  colours.PropertyChanged += colours_PropertyChanged;
  this.propertyGrid1.SelectedObject = colours;
}

private void colours_PropertyChanged(object sender, PropertyChangedEventArgs e) {
  this.propertyGrid1.Refresh();
}

private void button1_Click(object sender, EventArgs e) {
  ((Colours)this.propertyGrid1.SelectedObject).Reset();
}

答案 2 :(得分:6)

在试图记住我曾经使用的内容时发生了这个问题,并认为它可能对其他人有用。

您可以使用[RefreshProperties]属性触发对Property Grid的更新。

例如:

    [RefreshProperties(RefreshProperties.All)]
    public int MyProperty{ get; set; }

答案 3 :(得分:0)

使用 DotNetBar AdvPropertyGrid控件。您不需要任何iNotify调用即可对其进行更新。
每当任何对象属性更改时,它都会自动更新网格。