Verständnisproblem INotifyPropertyChanged

  • WPF
  • .NET 5–6

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Verständnisproblem INotifyPropertyChanged

    Moin,

    das mit den Events geht mir irgendwie nicht bei.


    Für das Binding in WPF ist das genannte Event notwendig. In den Docus findet man den Hinweis, dass alles ganz einfach ist und man nur das folgende braucht:


    C#-Quellcode

    1. public event PropertyChangedEventHandler PropertyChanged;
    2. private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    3. {
    4. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    5. }


    Ich frage mich hier nun, wo wird denn der EventHandler gesetzt? Sollte man nicht erwarten, dass irgendwo stehen muss

    C#-Quellcode

    1. this.PropertyChanged += MainWindow_PropertyChanged;


    Offensichtlich passiert das irgendwo im Hintergrund und man muss sich nicht drum kümmern.


    Jetzt habe ich aber das Problem bei einem sehr einfachen Stück Code, dass der EventHandler nicht automatisch gesetzt wird, sprich PropertyChanged ist NULL;

    Im Netz gibt es viel zu lesen zum Thema, doch hat bei mir nichts zur Lösung beigetragen.

    Spoiler anzeigen


    C#-Quellcode

    1. using System;
    2. using System.ComponentModel;
    3. using System.Runtime.CompilerServices;
    4. using System.Windows;
    5. using libExcelAddIn;
    6. using libExcelAddIn.Classes;
    7. using libExcelAddIn.Views;
    8. namespace AddInTest
    9. {
    10. /// <summary>
    11. /// Interaction logic for MainWindow.xaml
    12. /// </summary>
    13. public partial class MainWindow : Window, INotifyPropertyChanged
    14. {
    15. private string _text;
    16. public event PropertyChangedEventHandler PropertyChanged;
    17. public void NotifyPropertyChanged([CallerMemberName] string caller = "")
    18. {
    19. //PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));
    20. PropertyChanged(this, new PropertyChangedEventArgs(caller));
    21. }
    22. public string Text
    23. {
    24. get
    25. {
    26. return _text;
    27. }
    28. set
    29. {
    30. _text = value;
    31. NotifyPropertyChanged();
    32. }
    33. }
    34. private void Write(string text)
    35. {
    36. Text += text;
    37. }
    38. private void WriteLine(string text)
    39. {
    40. Write(text + Environment.NewLine);
    41. }
    42. public MainWindow()
    43. {
    44. InitializeComponent();
    45. DataContext = this;
    46. //this.PropertyChanged += MainWindow_PropertyChanged;
    47. WriteLine(DateTime.Now.ToString());
    48. }
    49. private void MainWindow_PropertyChanged(object sender, PropertyChangedEventArgs e)
    50. {
    51. throw new NotImplementedException();
    52. }
    53. private void Beenden_Click(object sender, RoutedEventArgs e)
    54. {
    55. Close();
    56. }
    57. private void Einstellungen_Click(object sender, RoutedEventArgs e)
    58. {
    59. ...
    60. }
    61. }
    62. }


    XML-Quellcode

    1. <Window x:Class="AddInTest.MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:local="clr-namespace:AddInTest"
    7. mc:Ignorable="d"
    8. Title="MainWindow" Height="450" Width="800">
    9. <Grid>
    10. <Grid.RowDefinitions>
    11. <RowDefinition Height="auto"/>
    12. <RowDefinition Height="*"/>
    13. </Grid.RowDefinitions>
    14. <Menu Grid.Row="0">
    15. <MenuItem Header="Beenden" Click="Beenden_Click"/>
    16. <MenuItem Header="Datenbank">
    17. <MenuItem Header="View Einstellungen" Click="Einstellungen_Click"/>
    18. </MenuItem>
    19. </Menu>
    20. <TextBox Grid.Row="1" Text="{Binding Text}">
    21. </TextBox>
    22. </Grid>
    23. </Window>




    Einfacher geht es ja kaum und ich finde keinen Ansatz, was da fehlen sollte. DataContext ist gesetzt, das wird häufig als Ursache genannt, verschiedene Instanzen verschiedener Klassen sind auch nicht vorhanden, ...

    Sieht jemand auf Anhieb, was da fehlt? Ich habe das mit anderen Projekten verglichen, in denen ebenfalls nur das Event und dessen Aufruf implementiert sind, und da läuft es nach Lehrbuch.

    Im Moment scheint bei mir der Wurm drin zu sein. Nix geht mehr, alles klemmt.

    Gruß

    MQ

    MasterQ schrieb:

    Offensichtlich passiert das irgendwo im Hintergrund und man muss sich nicht drum kümmern.

    Richtig. Die WPF kümmert sich darum wenn du ein Binding auf eine Eigenschaft im View setzt da hier das Event Abonniert wird und übernimmt alles für dich.

    MasterQ schrieb:

    Ich frage mich hier nun, wo wird denn der EventHandler gesetzt?

    Wie oben geschrieben kannst du das auch nicht prüfen.
    Deine ​MainWindow_PropertyChanged kannst du also löschen.

    Ich erkenne hier aber nicht wirklich eine Frage oder was nicht funktioniert? Das Binding auf ​Text scheint korrekt zu sein und funktioniert oder?
    Stelle bitte eine konkrete Frage.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Mein Problem ist

    Jetzt habe ich aber das Problem bei einem sehr einfachen Stück Code, dass der EventHandler nicht automatisch gesetzt wird, sprich PropertyChanged ist NULL;


    Vielleicht habe ich mich misverständlich ausgedrückt. Der EventHandler in meinem Code wird nicht automatisch von WPF selbst gestetzt und bleibt NULL. Das Binding funktioniert daher nicht, da das UI keine Rückmeldung über die Änderung erhält.

    Das Setzen des EventHandlers per Hand (im Spoiler) ist auskommentiert, es war nur ein Test um zu sehen, was passiert wenn ich den Automatismus ignoriere.

    Hier nochmal so wie ich denke, dass es sein müsste und wo PropertyChanged NULL ist.

    C#-Quellcode

    1. public partial class MainWindow : Window, INotifyPropertyChanged
    2. {
    3. private string _text;
    4. public event PropertyChangedEventHandler PropertyChanged;
    5. public void NotifyPropertyChanged([CallerMemberName] string caller = "")
    6. {
    7. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));
    8. }
    9. public string Text
    10. {
    11. get
    12. {
    13. return _text;
    14. }
    15. set
    16. {
    17. _text = value;
    18. NotifyPropertyChanged();
    19. }
    20. }
    21. private void Write(string text)
    22. {
    23. Text += text;
    24. }
    25. private void WriteLine(string text)
    26. {
    27. Write(text + Environment.NewLine);
    28. }
    29. public MainWindow()
    30. {
    31. InitializeComponent();
    32. DataContext = this;
    33. WriteLine(DateTime.Now.ToString());
    34. }
    35. private void Beenden_Click(object sender, RoutedEventArgs e)
    36. {
    37. Close();
    38. }
    39. private void Einstellungen_Click(object sender, RoutedEventArgs e)
    40. {
    41. ...
    42. }
    43. }



    Kurz, mache ich alles nach Lehrbuch, dann ist im Beispiel PropertyChanged NULL und ich weiß nicht warum.

    MasterQ schrieb:

    mache ich alles nach Lehrbuch
    Das ist aber glaub kaum nach Lehrbuch, dass dein Window INotifyPropertyChanged implementiert.
    INotifyPropertyChanged ist Aufgabe des Viewmodels (ich hoffe ist bekannt, was das ist).



    Dass dein PropertyChanged Null ist kann eiglich nur daran liegen, dass an das Objekt (zu dem Zeitpunkt noch) nicht gebunden wurde.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    MasterQ schrieb:

    hm, INotifyPropertyChanged ist doch Teil des DataContext und das steht bei mir auf this.
    ja - und?.
    kannst ma so probieren:

    C#-Quellcode

    1. public MainWindow()
    2. {
    3. DataContext = this;
    4. InitializeComponent();
    5. //this.PropertyChanged += MainWindow_PropertyChanged;
    6. WriteLine(DateTime.Now.ToString());
    7. }
    weiss aber nicht, obs hilft.
    Das Phänomen ist aufgeklärt.

    Es ist tatsächlich so, dass ein Window nicht mit dem Event PropertyChanged versehen werden kann.

    Das bissl um Property Text habe ich gerade in eine eigene Klasse ausgelagert und diese als DataContext für mein MainWindow gesetzt. Und schon klappt alles.

    Wieder was gelernt und gut zu wissen.

    Gruß

    MQ

    MasterQ schrieb:

    Das bissl um Property Text habe ich gerade in eine eigene Klasse ausgelagert und diese als DataContext für mein MainWindow gesetzt. Und schon klappt alles.
    Jo - das ist eigentlich die übliche Vorgehensweise beim MVVM-Pattern.
    Den würde ich dir sehr ans Herz legen.
    Im Tutbereich habich das Beispiel einer Anwendungs-Struktur veröfflicht, oder du beisst dich durch das Mammut-Tut von @Nofear23m

    Zwei unterschiedliche Lern-Ansätze (und inhaltlich weiche ich auch von NoFears Auffassungen ab):
    Meins ist eine lauffähige Solution mit wenig Erklärungen, und bei Fragen kannste fragen (im Forum - nicht im Tut)
    NoFears Tut versucht alles zu erklären, aber ich weiss grad nicht, ob die Codebasis des Tuts als Vorlage eigener Entwicklungen verwendugsfähig ist.