PropertyGrid не замечает изменений, измененных в коде?
У меня есть приложение Winform, которое использует цвет, чтобы выделить некоторые вещи. Я бы хотел, чтобы пользователи меняли "свои" цвета. В качестве упражнения я решил создать экземпляр класса со свойствами для цветов и назначить его сетке свойств (чтобы получить хороший редактор).
Кажется, что все нормально, но я подумал, что хотел бы позволить пользователям reset цвета (после того, как они поиграли и установили их на 20 оттенков бежевого). Итак, я добавил кнопку "reset" в мою форму, которая вернула свойства цвета моего объекта по умолчанию.
Однако кажется, что, пока он возвращает мои свойства объекта, сетка свойств не изменяется. Если после reset я создаю сетку свойств "Обновить", она имеет цвет reset.
Я предполагаю, что сетка свойств не знает, что базовый объект был изменен?
Есть ли что-то в этом сценарии или я должен просто принять его и вызвать метод Refresh, когда я reset мой объект?
Спасибо
(очень похожий вопрос здесь)
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();
}
}
Ответы
Ответ 1
Чтобы ответить на вопрос о том, почему PropertyGrid не изменяется, в документации MSDN для PropertyGrid говорится следующее:
Информация, отображаемая в сетке, представляет собой снимок свойств в момент назначения объекта. Если значение свойства объекта указанный в элементе SelectedObject, изменен в коде во время выполнения, новое значение не отображается до тех пор, пока в сетке не будет выполнено действие, которое вызывает обновление сетки.
Итак, похоже, что PropertyGrid не является автоматическим обновлением. Я думаю, что ключ к этому заключается в том, что PropertyGrid использует метод SelectedObject
вместо метода DataSource
, а последний подразумевает, что он, вероятно, прослушивает INotifyPropertyChanged.
Осталось то, что предложил LarsTech, и вручную обновляя сетку.
Ответ 2
Просто попробуйте обновить его:
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();
}
Ответ 3
Произошел этот вопрос, пытаясь вспомнить, что я использовал, и подумал, что это может быть полезно другим.
Вы можете использовать атрибут [RefreshProperties] для запуска обновлений в Property Grid.
например:
[RefreshProperties(RefreshProperties.All)]
public int MyProperty{ get; set; }
Ответ 4
Используйте элемент управления DotNetBar AdvPropertyGrid. Вам не нужен вызов iNotify
для его обновления.
Он автоматически обновляет сетку всякий раз, когда изменяется любое свойство объекта.