web-dev-qa-db-fra.com

L'événement PropertyChanged est toujours nul

J'ai le xaml (abrégé) suivant:

<TextBlock Text="{Binding Path=statusMsg, UpdateSourceTrigger=PropertyChanged}"/>

J'ai une classe singleton:

public class StatusMessage : INotifyPropertyChanged
{   
    private static StatusMessage instance = new StatusMessage();

    private StatusMessage() { }

    public static StatusMessage GetInstance()
    {
        return instance;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string status)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(status));
        }
    }

    private string statusMessage;
    public string statusMsg
    {
        get
        {
            return statusMessage;
        }
        set
        {
            statusMessage = value;
            OnPropertyChanged("statusMsg");
        }
    }
}

Et dans mon constructeur de fenêtre principale:

StatusMessage testMessage = StatusMessage.GetInstance();
testMessage.statusMsg = "This is a test msg";    

Je ne parviens pas à obtenir le bloc de texte pour afficher le message de test. Lorsque je surveille le code via le débogage, le PropertyChanged est toujours nul. Des idées?

35
Dave

Merci Jérôme! Une fois que j'ai défini le DataContext, il a commencé à fonctionner comme il se doit! J'ai ajouté ce qui suit au constructeur de la fenêtre principale à des fins de test:

 this.DataContext = testMessage;
18
Dave

Je suis tombé sur cela aujourd'hui et j'ai perdu un peu de temps dessus, et j'ai finalement compris. J'espère que cela vous fera gagner du temps à vous et aux autres.

S'il n'y a pas d'abonnés à votre événement, et que vous avez simplement déclaré les événements comme:

public event EventHandler SomeEventHappened;

ne référence nulle est alors attendue. La solution consiste à déclarer ce qui suit:

public event EventHandler SomeEventHappened = delegate { };

Cela garantira qu'il ne s'agit pas d'une référence nulle lorsque vous appelez en tant que

SomeEventHappened()

Un autre modèle que j'ai vu est de ne pas initialiser pour déléguer {} et vérifier à la place pour null:

var eventToRaise = SomeEventHappened;
if( eventToRaise != null )
{
    SomeEventHappened()
}
14
danielpops

Votre chaîne OnPropertyChanged doit correspondre exactement au nom de la propriété car elle est sensible à la casse.

Essayez de changer

OnPropertyChanged("StatusMsg");

à

OnPropertyChanged("statusMsg");

pdate: Aussi - vient de remarquer que vous vous liez à StatusMsg ('S' majuscule); donc le contrôle n'était pas lié à la propriété, ce qui est une autre raison pour laquelle il n'était pas mis à jour!

9
kiwipom

Juste au cas où: j'avais un problème similaire mais mon erreur était que la classe qui implémentait INotifyPropertyChanged était privée. Le rendre public a résolu mon cas.

4
lukaszk

J'ai également vu l'événement PropertyChanged être nul lorsque j'ai des données existantes affectées à la propriété liée aux données du contrôle:

<TextBlock Name="CarTireStatus" Text="{Binding TireStatus}" >Bad Text!</TextBlock>

Où cela fonctionne:

<TextBlock Name="CarTireStatus" Text="{Binding TireStatus}" ></TextBlock>
1
OutThere

dans mon cas, cela fonctionne:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;    // this row fixed everything
    }
    ****
    Some code here with properties etc
    ***
}
1
saha0404

Autre point - pour que PropertyChanged soit nul, assurez-vous de lier l'objet au DataContext, puis de définir le chemin d'accès au lieu d'attribuer directement la propriété au champ d'interface utilisateur.

1
vancutterromney

Il y a quelques éléments à vérifier lors de l'observation de l'objet événement PropertyChanged comme null.

  1. Assurez-vous que le nom de la propriété transmis en tant qu'argument lors du déclenchement de l'événement correspond réellement au nom de la propriété que vous ciblez.

  2. Assurez-vous que vous utilisez une seule instance de l'objet qui contient la propriété à laquelle vous vous liez.

Pour l'élément numéro deux, cela peut être fait en plaçant simplement un point d'arrêt sur le constructeur de classe pour l'objet qui héberge la propriété qui est liée. Si le point d'arrêt est déclenché plusieurs fois, vous avez un problème et devez résoudre le nombre d'instances d'objets en une seule instance que votre runtime invoque via XAML.

Par conséquent, il est préférable d'implémenter cette classe en tant que modèle singleton afin de pouvoir garantir une seule instance de l'objet au moment de l'exécution.

0
Scott Nimrod