12

我有一个 Winform 应用程序,它使用颜色来突出显示某些内容。我想允许用户更改“他们的”颜色。作为一个练习,我想我会创建一个具有颜色属性的类的实例,并将其分配给一个属性网格(以获得一个不错的编辑器)

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

但是,似乎虽然它设置了我的对象的属性,但属性网格并没有改变。如果在重置后,我做了一个属性网格“刷新”,它具有重置颜色。

我假设属性网格不知道基础对象已更改?

在这种情况下是否缺少某些东西,或者我应该接受它并在重置对象时调用 Refresh 方法?

谢谢

(这里非常相似的问题)

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

5 回答 5

14

为了回答您关于 PropertyGrid 为何不改变的问题,PropertyGrid 的 MSDN 文档这样说:

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

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

您将得到 LarsTech 的建议并手动刷新网格。

于 2012-04-12T19:08:42.203 回答
9

只需尝试刷新它:

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();
}
于 2012-04-10T16:27:49.640 回答
7

在试图记住我曾经使用过的东西并认为它可能对其他人有用的过程中发生了这个问题。

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

例如:

    [RefreshProperties(RefreshProperties.All)]
    public int MyProperty{ get; set; }
于 2016-10-26T15:06:40.950 回答
0

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

于 2019-08-24T15:07:03.777 回答
0

在 .Net 4.7.2 项目中,我发现调用yourPropGridInstanceHere.ExpandAllGridItems()会导致属性网格根据当前的“SelectedObject”刷新其值。

请注意,无需调用 collapse 方法即可发生这种情况。

当然,如果您折叠了某些类别,这可能对您不起作用,但至少在更简单的情况下,它可以避免必须实施INotifyPropertChanged或必须不断更新SelectedObject属性。

我还没有用任何其他 .Net 版本对此进行测试,但我怀疑它适用于所有版本。

于 2021-08-30T21:59:45.663 回答