2012-12-01 10 views
7

Durante la lettura Pro WPF in C# 2010 l'autore scrive:Modifica notifica senza INotifyPropertyChanged? (Estratto da Pro WPF in C# 2010)

"si può sollevare un evento per ogni proprietà In questo caso, l'evento deve avere il nome PropertyNameChanged (per esempio. , UnitCostChanged). Spetta a te licenziare l'evento quando la proprietà viene modificata ".

Qualcuno potrebbe confermare questa funzione? Stavo sperimentando e non in grado di riprodurre questo comportamento (voglio vedere se questo funziona così allora posso fare alcuni esperimenti con System.Reflection.Emit per creare tipi dinamici)

EDIT: vorrei chiarire l'enfasi qui è quello di implementare la notifica delle modifiche senza implementare INotifyPropertyChanged, in quanto questo è ciò che il libro sta sostenendo

Ecco il POCO sto testando con:

public class Employee 
{ 
    private string _FirstName; 
    public string FirstName 
    { 
     get 
     { 
      return _FirstName; 
     } 
     set 
     { 
      if (_FirstName != value) 
      { 
       _FirstName = value; 
       if (FirstNameChanged != null) 
       { 
        FirstNameChanged(this, new PropertyChangedEventArgs("FirstName")); 
       } 
      } 
     } 
    } 
} 

ho legato ad un DataGrid e hanno un timer in aggiornamento in background la proprietà FirstName casualmente ogni pochi secondi OND ma DataGrid non genera

<DataGrid x:Name="dgEmployees" ItemsSource="{Binding ElementName=mainWindow, Path=MyEmployees}"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Header="FirstName" Binding="{Binding Path=FirstName}" /> 
     </DataGrid.Columns> 
    </DataGrid> 

L'evento FirstNameChanged è sempre nullo (ho pensato che il motore di associazione può abbonarsi automaticamente se ha rilevato che secondo la convenzione di denominazione). MyEmployees è solo una ObservableCollection

Qualcuno può confermare se questa funzione menzionata dall'autore, funziona davvero e se sto facendo un errore?

EDIT: a beneficio di tutti coloro che pensa che io sia mal interpretare il testo:

"È possibile utilizzare tre approcci per risolvere questo problema:

È possibile effettuare tutte le proprietà della classe Product una proprietà di dipendenza che utilizza la sintassi che hai appreso nel Capitolo 4. (In questo caso, la classe deve derivare da DependencyObject.) Sebbene questo approccio faccia funzionare WPF per te (che è bello), rende il massimo senso in elementi-classi che hanno un ap visivo pearance in una finestra. Non è l'approccio più naturale per le classi di dati come il prodotto .

È possibile generare un evento per ogni proprietà. In questo caso, l'evento deve avere il nome PropertyNameChanged (ad esempio, UnitCostChanged). Spetta a te a attivare l'evento quando la proprietà viene modificata.

È possibile implementare l'interfaccia System.ComponentModel.INotifyPropertyChanged , che richiede un singolo evento denominato PropertyChanged. È necessario quindi aumentare l'evento PropertyChanged ogni volta che una proprietà cambia e indicare quale proprietà è stata modificata fornendo il nome della proprietà come una stringa. E 'ancora fino a di alzare questo evento quando una proprietà cambia, ma non è necessario definire un evento separato per ogni proprietà."

+2

Non sono sicuro se che la sintassi funzionerà, ma è abbastanza sicuro che serve per decorare la classe come implementazione INotifyPropertyChanged – Paparazzi

+0

No, questo è esattamente quello che ho Sto cercando di evitare - nel libro, menziona le 3 tecniche sono a.) usa DependencyProperties b.) usa INotifyPropertyChanged (che sono già familiare con) c.) usa questo approccio basato sulla convenzione che NON implementa INotifyPropertyChanged. . Questo è il tipo di tutto il punto quello che sto testando qui :) – blue18hutthutt

+0

OK capisco ma non penso che sia quello che viene richiesto. È possibile generare l'evento direttamente senza un metodo NotifyPropertyChanged ma penso che sia ancora necessario implementare INotifyPropertyChanged. – Paparazzi

risposta

9

vorrei dire che è molto possibile implementare le notifiche di modifica della tua POCO di senza utilizzare né INotifyPropertyChanged o di dipendenza proprietà, come è in fase di sostenuto nel libro, a meno che non sto completamente manca il punto della questione.

Se si alza un evento chiamato {} PROPERTYNAME Modificato dal POCO quando il valore di una proprietà è cambiata, il sistema di rilegatura WPF prenderà che fino, e aggiornare le associazioni interessate.

Vedere questo piccolo programma per una dimostrazione - è la cosa più semplice che potessi pensare, ma suppongo che dovrebbe funzionare anche nel tuo caso.

XAML:

<StackPanel> 
    <TextBlock Text="{Binding Name}" /> 
    <Button Content="Change name" Click="changeNameClick" /> 
</StackPanel> 

Codice-behind:

public partial class Window1 : Window 
{ 
    private SimpleObject so = new SimpleObject(); 

    public Window1() 
    { 
     InitializeComponent(); 

     this.so = new SimpleObject(); 
     so.Name = "Initial value"; 

     this.DataContext = so; 

     var t = new DispatcherTimer(
      TimeSpan.FromSeconds(1), 
      DispatcherPriority.Normal, 
      (s, e) => { this.so.Name = "Name changed at: " + DateTime.Now.ToString(); }, 
      Dispatcher); 
    } 

    private void changeNameClick(object sender, RoutedEventArgs e) 
    { 
     this.so.Name = "New value!!"; 
    } 
} 

public class SimpleObject 
{ 
    private string mName = null; 

    public string Name 
    { 
     get { return mName; } 
     set 
     { 
      if (mName != value) 
      { 
       mName = value; 

       if (NameChanged != null) 
        NameChanged(this, EventArgs.Empty); 
      } 
     } 
    } 

    public event EventHandler NameChanged; 
} 
+1

PERFETTO! Sapevo che non ero pazzo lol. Il mio codice originale ora funziona, ma solo dopo aver cambiato "PropertyChangedEventHandler" in un semplice "EventHandler" ... un'idea del perché? Questa "funzionalità" è documentata ovunque? Fantastico, grazie mille. – blue18hutthutt

+1

Hehe, no scusa, non ho davvero idea del perché sia ​​così. Ricordo di aver sentito parlare di questo qualche tempo fa, ma non l'ho mai usato nel mio codice. E non riesco davvero a trovare alcuna documentazione reale da nessuna parte, quindi probabilmente non è una tecnica molto diffusa .. –

+1

Ho alcune informazioni aggiuntive se sei interessato - dall'ispezione, il PropertyDescriptor predefinito sul tipo POCO è un'istanza di ReflectPropertyDescriptor lazy-loaded - di particolare interesse è la proprietà booleana SupportsChangeEvents. È impostato su true dal runtime se la classe segue la convenzione di denominazione propertynameChanged (sebbene non funzioni a meno che non abbia usato un EventHandler semplice) o implementa INotifyPropertyChanged. L'assenza di entrambi farà sì che questo sia falso. http://msdn.microsoft.com/en-us/library/system.componentmodel.propertydescriptor.supportschangeevents.aspx – blue18hutthutt

-1

No, con WPF, è necessario utilizzare DependencyProperties o INotifyPropertyChanged. Per collezioni, INotifyCollectionChanged farà anche il trucco.

+0

A quanto pare puoi - vedi la risposta. – blue18hutthutt

+1

In realtà c'è una quarta via: puoi sempre aumentare manualmente il metodo UpdateTarget() su BindingExpression ma non sono sicuro che conterei che – blue18hutthutt

Problemi correlati