2012-12-01 4 views
7

Während Pro WPF in C# Lesen 2010 schreibt der Autor:Benachrichtigung ändern ohne INotifyPropertyChanged? (Auszug aus Pro WPF in C# 2010)

„Sie ein Ereignis für jede Eigenschaft erhöhen können in diesem Fall das Ereignis den Namen PropertyNameChanged (zum Beispiel hat. (UnitCostChanged). Es liegt an Ihnen, das Ereignis auszulösen, wenn die Eigenschaft geändert wird. "

Könnte jemand bestätigen, dass diese Funktion funktioniert? Ich experimentierte und nicht in der Lage, dieses Verhalten zu reproduzieren (Ich möchte sehen, ob das funktioniert so, dann kann ich einige mit System.Reflection.Emit experimentieren tun dynamische Typen erstellen)

EDIT: ich sollte die Betonung liegt hier klären

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

ich an ein Datagrid gebunden es und einen Timer im Hintergrund Update haben: an Änderungsbenachrichtigung OHNE Umsetzung INotifyPropertyChanged zu implementieren, als das, was ist das Buch

Hier ist die POCO ich mich entschieden behauptet die FirstName-Eigenschaft nach dem Zufallsprinzip alle paar Sekunden onds aber das Datagrid wird nie ausgelöst

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

Das FirstNameChanged Ereignis immer null ist (ich dachte, das Bindungsmodul, um es automatisch anmelden kann, wenn sie es nach der Namenskonvention erkannt). MyEmployees ist nur eine ObservableCollection

Kann jemand bestätigen, wenn dieses Feature der Autor erwähnt, funktioniert tatsächlich und wenn ich einen Fehler mache?

EDIT: zugunsten von jedermann, das ich falsch interpretiert den Text meint:

„können Sie drei Ansätze, um dieses Problem zu lösen:

Sie können jede Eigenschaft in der Produktklasse machen Eine Abhängigkeitseigenschaft, die die Syntax verwendet, die Sie in Kapitel 4 gelernt haben. (In diesem Fall muss Ihre Klasse von DependencyObject abgeleitet werden.) Obwohl dieser Ansatz WPF dazu bringt, die Arbeit für Sie zu erledigen (was nett ist), macht es am meisten Sinn in Element-Klassen, die eine visuelle ap haben Schein in einem Fenster. Es ist nicht der natürlichste Ansatz für Datenklassen wie Produkt.

Sie können für jede Eigenschaft ein Ereignis auslösen. In diesem Fall muss das Ereignis den Namen PropertyNameChanged haben (z. B. UnitCostChanged). Es liegt an Ihnen, das Ereignis auszulösen, wenn die Eigenschaft geändert wird.

Sie können die Schnittstelle System.ComponentModel.INOtifyPropertyChanged implementieren, die ein einzelnes Ereignis namens PropertyChanged erfordert. Sie müssen dann das PropertyChanged-Ereignis auslösen, wenn sich eine Eigenschaft ändert, und angeben, welche -Eigenschaft geändert wurde, indem Sie den Eigenschaftsnamen als Zeichenfolge angeben. Es ist immer noch bis zu Sie dieses Ereignis, wenn ein Eigenschaftsänderungen zu erhöhen, aber Sie brauchen nicht ein separates Ereignis für jede Eigenschaft zu definieren.“

+2

nicht sicher, ob das Syntax funktioniert, aber Sie ziemlich sicher, müssen Sie die Klasse schmücken, wie die Umsetzung INotifyPropertyChanged – Paparazzi

+0

Nein, das ist genau das, was ich Ich versuche zu vermeiden - in dem Buch erwähnt es die 3 Techniken sind a.) DependencyProperties verwenden b.) verwenden INotifyPropertyChanged (mit denen ich bereits vertraut bin) c.) verwenden diese Konvention-basierte Ansatz, die nicht implementiert INotifyPropertyChanged. Das ist der Sinn von was ich hier teste :) – blue18hutthutt

+0

OK verstehen, aber ich glaube nicht, dass das ist, was behauptet wird. Sie können das Ereignis direkt ohne eine NotifyPropertyChanged-Methode auslösen, aber ich denke, dass Sie INotifyPropertyChanged noch implementieren müssen. – Paparazzi

Antwort

9

Ich würde sagen, dass es sehr wohl möglich ist, Eigenschaften ohne Verwendung von entweder INotifyPropertyChanged oder Abhängigkeit zu implementieren, wie es in dem Buch behauptet hat ist, es sei denn, ich völlig den Punkt der Frage fehlt bin.

Wenn Sie ein Ereignis auslösen genannt {} Property geändert von Ihrem POCO, wenn der Wert einer Eigenschaft geändert hat, wird das WPF-Bindungssystem, dass abholen und aktualisiert die entsprechenden Bindungen.

Sehen Sie dieses kleine Programm für eine Demonstration - es ist die einfachste Sache, die ich denken könnte, aber ich denke, es sollte auch in Ihrem Fall funktionieren.

XAML:

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

-Code-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

PERFEKT! Ich wusste, dass ich nicht verrückt bin, lol. Mein ursprünglicher Code funktioniert jetzt aber erst, nachdem ich "PropertyChangedEventHandler" in einen einfachen "EventHandler" geändert habe ... eine Idee, warum das so ist? Ist dieses "Feature" überall dokumentiert? Fantastisch, vielen Dank SO VIEL – blue18hutthutt

+1

Hehe, nein Entschuldigung, ich habe wirklich keine Ahnung warum das so ist. Ich erinnere mich, dass ich vor einiger Zeit davon gehört habe, aber ich habe es nie in meinem eigenen Code verwendet. Und ich kann wirklich nirgendwo echte Dokumentation finden, also ist es wahrscheinlich keine sehr weit verbreitete Technik. –

+1

Ich habe einige zusätzliche Erkenntnisse, wenn Sie interessiert sind - von Inspektion, die Standard-PropertyDescriptor auf den POCO-Typ ist Lazy-geladen eine Instanz von ReflectPropertyDescriptor - von besonderem Interesse ist die Boolean-Eigenschaft SupportsChangeEvents. Dies wird von der Laufzeit auf true gesetzt, wenn die Klasse der Namenskonvention propertynameChanged folgt (obwohl sie nicht funktioniert, wenn ich nicht einen einfachen EventHandler verwende) oder INotifyPropertyChanged implementiert. Die Abwesenheit von beiden wird dazu führen, dass dies falsch ist. http://msdn.microsoft.com/en-us/library/system.componentmodel.propertydescriptor.supportschangeevents.aspx – blue18hutthutt

-1

Nein, mit WPF, Sie DependencyProperties oder INotifyPropertyChanged verwenden müssen. Für Sammlungen, INotifyCollectionChanged wird auch den Trick tun.

+0

Anscheinend können Sie - siehe Antwort. – blue18hutthutt

+1

Es gibt tatsächlich einen vierten Weg - Sie können immer die UpdateTarget() -Methode für die BindingExpression manuell auslösen, aber nicht sicher, dass ich das zählen würde – blue18hutthutt

3

Das von Ihnen erwähnte Muster gilt sowohl für WPF als auch für Windows Forms (WinForms).

+0

Danke für den Link! Großartig, um endlich einen definitiven Link auf MSDN zu haben, der es beschreibt – blue18hutthutt