2012-09-17 1 views
9

J'ai un contrôle personnalisé hérité du contrôle TextBox. Je voudrais implémenter l'interface INotifyPropertyChanged dans mon contrôle personnalisé. Mon problème est que lorsque j'essaie de déclencher un événement PropertyChanged, le gestionnaire d'événements PropertyChanged est toujours null.INotifyPropertyChanged dans UserControl

Quelqu'un peut-il m'aider? Le gestionnaire d'événements PropertyChanged est également null.

+0

Cela ne fonctionne pas comme vous l'avez fait. Créez simplement une classe supplémentaire et implémentez l'interface de notification ici et appliquez cette classe au DataContext de UserControl. Et cela fonctionnera comme vous avez besoin. –

Répondre

12

Ceci sera toujours vrai jusqu'à ce qu'un objet s'abonne à l'événement PropertyChanged.

En règle générale, si vous effectuez un contrôle personnalisé, cependant, vous n'utiliserez pas INotifyPropertyChanged. Dans ce scénario, vous devez créer un Custom Dependency Property à la place. Normalement, les objets de dépendance (c'est-à-dire: les contrôles) utiliseront tous des propriétés de dépendance, et INPC est utilisé par les classes qui deviennent les DataContext de ces objets. Cela permet au système de reliure de fonctionner correctement.

6

Qu'attendiez-vous? L'événement PropertyChanged est utilisé par le code d'interface utilisateur, mais pas en ce sens que vous écrivez. Les contrôles n'implémentent jamais INPC (abréviation de INotifyPropertyChanged), ils sont liés à l'objet que ont implémenté INPC. De cette façon, certaines propriétés de l'interface utilisateur, par ex. la propriété Text sur le contrôle TextBox est liée à une propriété sur une telle classe. C'est la base de l'architecture MVVM.

exemple, vous pouvez écrire le code XAML suivant:

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

et que vous définissez le contexte de données pour TextBlock (ou l'un de ses ancêtres, DataContext se propage) dans le code de la manière suivante:

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

Et maintenant pour la classe elle-même:

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

maintenant, chaque fois que vous ch ange la propriété Title, que ce soit dans le code ou via une autre liaison, l'interface utilisateur sera automatiquement actualisée. Google pour la liaison de données et MVVM.

+2

Ceci met à jour le contrôle chaque fois que les données changent, mais je suppose que l'OP essaye d'implémenter la liaison bidirectionnelle où la source de données est automatiquement mise à jour par UserControl. On peut supposer qu'il existe un moyen de notifier que le contrôle utilisateur a mis à jour la propriété, mais je ne l'ai pas encore trouvé. – misnomer

1

Faites comme je l'ai dit dans les commentaires. Cela ne fonctionne pas comme vous l'avez fait. Créez simplement une classe supplémentaire et implémentez Notification Interface là et appliquez cette classe au DataContext du UserControl. Et cela fonctionnera comme vous avez besoin.

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)); 
     } 
    } 
Questions connexes