Announcement

Collapse
No announcement yet.

WPF Datagrid aktualisieren

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • WPF Datagrid aktualisieren

    Ein WPF HeaderedContentControl mit mehreren Tab-Seiten. Auf Tabseite A befindet sich ein Datagrid, das mit der Artikelliste gebunden ist. Der User selektiert ein Item mit der Maus, das selektierte Item ist mit Artikel gebunden. Durch eine Programmfunktion werden nun Daten in diesem Item verändert, ohne dass der User direkt im Datagrid editiert. Im Datagrid bleibt aber der alte Inhalt erhalten. Ein Aufruf von OnPropertyChanged für den Artikel oder die Artikelliste bringt keine Aktualisierung. Wenn ich aber die Tabseite wechsle und dann auf Seite A zurückgehe, zeigt das Grid die aktualisierten Daten an. Wie kann ich das Grid dazu bewegen, auch ohne unnötige Klicks die Anzeige zu aktualisieren?

    Danke - Günther
    Günther

  • #2
    Das Datagrid akutallisiert sich von selbst wenn in deinem Model aus dem die Daten kommen das
    Code:
    System.ComponentModel.INotifyPropertyChanged
    interface implementieren.
    Damit kannst du in der set Methode das
    Code:
    PropertyChanged
    Eent auslösen.


    Beispiel:
    Code:
     public class clBasicModel : System.ComponentModel.INotifyPropertyChanged
        {
            public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    
            protected void RaisePropertyChanged(string propertyName)
            {
                System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
                if ((propertyChanged != null))
                {
                    propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
                }
            }
        }
    Code:
        public class clAddPlantdata : clBasicModel
        {
            private bool oDeleteField;
            public bool oDelete
            {
                get
                {
                    return this.oDeleteField;
                }
                set
                {
                    this.oDeleteField = value;
                    this.RaisePropertyChanged("oDelete");
                }
            }
    }

    Comment


    • #3
      Mein ViewModel ist von INotifyPropertyChanged abgeleitet. Ich denke mal menn das nicht so wäre, würde gfoidl mir den Hintern versohlen, wo er sich doch solche Mühe mit mir gemacht hat. Statt der allgemein vorgeschlagene Methode, die einen String übergibt bei dem der Compiler die Schreibfehler nicht bemerkt und der vergessen wird, wenn der Variablenname geändert wird, verwende ich die Weiterentwicklung von gfoidl:

      Code:
              protected virtual void OnPropertyChanged<T>(Expression<Func<T>> exp)
              {
                  MemberExpression me = exp.Body as MemberExpression;
                  string propertyName = me.Member.Name;
                  var handler = this.PropertyChanged;
                  if (handler != null)
                      handler(this, new PropertyChangedEventArgs(propertyName));
              }
      Code:
              private List<ArtikelModel> _ArtikelListe;
              public List<ArtikelModel> ArtikelListe
              {
                  get { return this._ArtikelListe; }
                  set
                  {
                      this._ArtikelListe = value;
                      this.OnPropertyChanged(() => ArtikelListe);
                  }
              }
              private ArtikelModel _Artikel;
              public ArtikelModel Artikel
              {
                  get { return this._Artikel; }
                  set
                  {
                      _Artikel = value;
                      this.OnPropertyChanged(() => Artikel);
                      CreateLagerortListe();
                  }
              }
      Es scheint mir aber so zu sein, dass nur die Adresse der Property geprüft wird und nicht der Inhalt einer Liste. Ich benutze jetzt eine zwar nicht sehr elegante, aber gut funktionierende Lösung, indem ich nach der Änderung der aktuellen Daten einmal RefreshArtikelListe aufrufe.


      Code:
            void RefreshArtikelListe()
              {
                  List<ArtikelModel> L = ArtikelListe;
                  ArtikelModel A = Artikel;
                  ArtikelListe = null;
                  Artikel = null;
                  ArtikelListe = L;
                  Artikel = A;
              }
      Gruß - Günther
      Günther

      Comment


      • #4
        Hallo Günther,

        stimmt

        Anmerkung: ich hab einfach drauflos geschrieben -> das wichtige steht im letzten Satz (mfG Gü ist nicht gemeint ).

        Eine genaue Antwort für dieses Verhalten hab ich nicht, nur Mutmaßungen.
        Auf welcher Objekt für das Programm die Änderungen aus? Bzw. werden sicher diese Änderungen an das ViewModel weitergegeben so dass dieses eben via INotifyPropertyChanged die View aktualisieren kann?

        Wenn ich die Zusammenhänge und den Code in RefreshArtikelListe richtig verstehe, könnte auch hier der Teufel im Detail liegen. Und zwar wird ein neues Objekt erstellt, d.h. auch eine neue Referenz. Diese wird zwar per INotifyPropertyChanged bekannt gemacht, aber das muss - v.a. in Verbindung mit Tabs - WPF nicht reichen. Die Hintergründe sind hierfür etwas schwer zu erklären da sie mit UI-Recycling, Caching, etc. zu tun, aber das soll hier egal sein.
        Jedenfalls ist es besser nicht ein neues Objekt zu erstellen, sondern das Objekt zu behalten und alles Einträge zu löschen und neu hinzuzufügen. Vorzugsweise in eine ObservableCollection<T>, da diese INotifyCollectionChanged implementiert und dieses wird hier benötigt.

        mfG Gü
        "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

        Comment


        • #5
          Hallo Günther,

          wußte ich ;-)

          Mit ObservableCollection<T> werde ich mich nochmal beschäftigen, das war ja schon mal ein Thema, glaub ich. Aber alle Einträge löschen und neu hinzufügen finde ich eigentlich noch unschöner...

          LG, Günther
          Günther

          Comment


          • #6
            Hallo Günther,

            schön finde ich es auch nicht, aber letzte Woche kämpfte ich auch mit so einem Problem da ich auch einfach eine neue Collectino erstellt habe. Irgendwie wollte es einfach nicht. Durch Löschen/Hinzufügen dann schon.

            Warum genau das so ist weiß ich nicht. Ich hab nur eine Theorie: WPF speichert ja vieles in einer Hashtabelle und so denke ich dass dass das mit dem DataContext passiert. Zumal DepenedencyProperties im Spiel sind und diese werden sicher in einer Hashtabelle gespeichert. D.h. entscheidend ist GetHashCode. Wenn nun ein neues Objekt (hier: Collection) erstellt wird, so ist der HashCode ein anderen und WPF findet mit diesem nichts, bzw. verwendet immer noch das alte bekannte.
            Tja, durch das PropertyChanged sollte das bekannt gemacht werden dachte ich, aber dem ist scheinbar nicht so wenn die UI nicht aktiv ist. Hier schiebe ich die "Schuld" auf das Recycling der UI. D.h. wenn die UI nicht aktiv ist, das lässt sich z.B. beim Wechseln von einem Tab zu einem anderen Tab mit ganz anderen Inhalt beobachten, werden die Events auch nicht behandelt.

            Wie gesagt, ich habs nicht geprüft. Das ist nur meine Theorie damit ich "inneren Frieden mit WPF schließen kann"

            mfG Gü
            "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

            Comment

            Working...
            X