2012-09-17 15 views
9

Ich habe ein benutzerdefiniertes Steuerelement, das von TextBox-Steuerelement geerbt wird. Ich möchte die INotifyPropertyChanged Schnittstelle in meinem benutzerdefinierten Steuerelement implementieren.INotifyPropertyChanged in UserControl

public class CustomTextBox : TextBox, INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void NotifyPropertyChanged(string info) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
    } 
} 

Mein Problem ist, wenn ich zu einem erhöhten Property Ereignisse versuche der Property Event-Handler immer null ist.

Jeder kann mir helfen?

+0

Es funktioniert nicht wie du getan hast. Erstellen Sie einfach eine zusätzliche Klasse und implementieren Sie die Notification Interface dort und wenden Sie diese Klasse auf den DataContext des UserControls an. Und es wird funktionieren, wie du es brauchst. –

Antwort

12

Der Ereignishandler PropertyChanged ist immer null.

Dies wird immer wahr sein, bis etwas zum Ereignis PropertyChanged abonniert wird. Wenn Sie ein benutzerdefiniertes Steuerelement erstellen, verwenden Sie . In diesem Szenario würden Sie stattdessen eine Custom Dependency Property machen. Normalerweise werden die Abhängigkeitsobjekte (dh: Steuerelemente) alle Abhängigkeitseigenschaften verwenden, und INPC wird von den Klassen verwendet, die die DataContext dieser Objekte werden. Dadurch kann das Bindungssystem ordnungsgemäß funktionieren.

6

Was haben Sie erwartet? PropertyChanged-Ereignis wird von UI-Code verwendet, aber nicht in dem Sinne, in dem Sie schreiben. Controls implementieren nie INPC (kurz für INotifyPropertyChanged), sie sind verpflichtet, das Objekt zu implementieren, das INPC implementiert hat. Auf diese Weise können bestimmte UI-Eigenschaften, z.B. Die Text -Eigenschaft für das TextBox-Steuerelement ist an eine Eigenschaft für eine solche Klasse gebunden. Dies ist die Grundlage der MVVM-Architektur.

Beispiel, würden Sie das folgende XAML-Code schreiben:

<TextBlock x:Name="txtBox" Text="{Binding Title}" /> 

Und Sie setzen den Datenkontext für TextBlock- im Code auf folgende Weise (oder einem seiner Vorgänger, ist Datacontext propagiert):

txtBox.DataContext = new Movie {Title = "Titanic"}; 

Und nun die Klasse selbst:

public class Movie : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void NotifyPropertyChanged(string info) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
    } 

    private string _title; 
    public string Title 
    { 
     get { return _title; } 
     set 
     { 
      if (_title == value) return; 

      _title = value; 
      NotifyPropertyChanged("Title"); 
     } 
    } 
} 

nun, wenn Sie ch Wenn Sie die Titeleigenschaft auswählen, wird die Benutzeroberfläche automatisch aktualisiert, unabhängig davon, ob sie im Code oder über eine andere Bindung erfolgt. Google für Datenbindung und MVVM.

+2

Dies aktualisiert das Steuerelement, wenn sich die Daten ändern, aber ich nehme an, dass das OP versucht, eine bidirektionale Bindung zu implementieren, bei der die Datenquelle automatisch vom UserControl aktualisiert wird. Vermutlich gibt es eine Möglichkeit zu benachrichtigen, dass das Benutzersteuerelement die Eigenschaft aktualisiert hat, aber ich habe das noch nicht gefunden. – misnomer

1

Tun Sie es wie ich in den Kommentaren sagte. Es funktioniert nicht wie du es getan hast. Erstellen Sie einfach eine zusätzliche Klasse und implementieren Sie Notification Interface dort und wenden Sie diese Klasse auf die DataContext der UserControl. Und es wird funktionieren, wie du es brauchst.

public partial class W3 : UserControl 
    { 
     WeatherViewModel model = new WeatherViewModel(); 

     public W3() 
     { 
      InitializeComponent(); 
      this.DataContext = model; 
     } 

     public void UpdateUI(List<WeatherDetails> data, bool isNextDays) 
     { 
      model.UpdateUI(data, isNextDays); 
     } 
    } 

    class WeatherViewModel : INotifyPropertyChanged 
    {  

     public void UpdateUI(List<WeatherDetails> data, bool isNextDays) 
     { 
      List<WeatherDetails> weatherInfo = data; 
      if (weatherInfo.Count != 0) 
      { 
       CurrentWeather = weatherInfo.First(); 
       if (isNextDays) 
        Forecast = weatherInfo.Skip(1).ToList(); 
      } 
     } 

     private List<WeatherDetails> _forecast = new List<WeatherDetails>(); 

     public List<WeatherDetails> Forecast 
     { 
      get { return _forecast; } 
      set 
      { 
       _forecast = value; 
       OnPropertyChanged("Forecast"); 
      } 
     } 

     private WeatherDetails _currentWeather = new WeatherDetails(); 

     public WeatherDetails CurrentWeather 
     { 
      get { return _currentWeather; } 
      set 
      { 
       _currentWeather = value; 
       OnPropertyChanged("CurrentWeather"); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     private void OnPropertyChanged(string propertyName) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    }