8

Ho un'applicazione Winform che usa il colore per evidenziare alcune cose. Vorrei consentire agli utenti di cambiare i "loro" colori. Come esercizio, ho pensato di creare un'istanza di una classe, con proprietà per i colori, e assegnarla a una griglia di proprietà (per ottenere un editor piacevole).PropertyGrid non rileva le proprietà modificate nel codice?

Questo sembra funzionare bene, ma ho poi pensato che mi piacerebbe consentire agli utenti di ripristinare i colori (dopo averli giocati e impostarli su 20 tonalità di beige). Così, ho aggiunto un pulsante "Ripristina" al mio modulo, che riporta le proprietà del colore del mio oggetto ai valori predefiniti.

Tuttavia, sembra che mentre si ripristinano le proprietà dell'oggetto, la griglia delle proprietà non cambia. Se, dopo il reset, faccio una griglia di proprietà "Aggiorna", ha il colore di reset.

Suppongo che la griglia delle proprietà non sappia che l'oggetto sottostante è stato modificato?

C'è qualcosa che manca in questo scenario, o dovrei semplicemente accettarlo e chiamare il metodo di aggiornamento quando resetto il mio oggetto?

Grazie

(domanda molto simile 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")); 
    } 
} 

seguito al mio commento di "nulla sottoscrive l'INotifyPropertyChanged.PropertyChanged", qual è lo svantaggio in subsclassing il controllo PropertyGrid in modo che lo faccia?

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

risposta

9

Per rispondere alla tua domanda sul perché il PropertyGrid non cambia, la documentazione MSDN per la PropertyGrid Dì questo:

Le informazioni visualizzate nella griglia sono un'istantanea delle proprietà al momento dell'assegnazione dell'oggetto. Se un valore di proprietà dell'oggetto specificato da SelectedObject viene modificato nel codice in fase di esecuzione, il nuovo valore non viene visualizzato finché non viene intrapresa un'azione nella griglia che provoca l'aggiornamento della griglia.

Quindi, sembra che il controllo PropertyGrid non sia un aggiornamento automatico. Penso che l'idea sia che PropertyGrid usa il metodo SelectedObject invece di un metodo DataSource, e quest'ultimo implicherebbe probabilmente che ascolti INotifyPropertyChanged.

Si rimane con ciò che LarsTech ha suggerito e l'aggiornamento manuale della griglia.

+0

Sì, questo praticamente lo riassume. – LarsTech

6

Basta provare rinfrescante che:

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

Supponendo si avrà più proprietà, è possibile utilizzare il vostro evento PropertyChanged. Vorrei modificare la classe Color in questo modo:

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

Poi il modulo sarà simile a questa:

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(); 
} 
+0

Ciao, grazie, che è praticamente quello che avevo già. Ero più interessato al motivo per cui la griglia di proprietà stessa non si accorge che la proprietà è cambiata. Nulla (ad esempio il controllo PropertyGrid) si abbona all'evento "PropertyChanged". Certo ... potrei farlo da solo, come hai, ma perché? Potrebbe essere che il controllo PropertyGrid non abbia proprietà associate, quindi non ascolta l'evento INotifyPropertyChanged? –

4

È accaduto attraverso questa domanda nel cercare di ricordare ciò che usavo e ho pensato che potesse essere utile agli altri.

È possibile utilizzare l'attributo [RefreshProperties] per attivare gli aggiornamenti alla griglia Proprietà.

esempio:

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