none
Benachrichtigt werden wenn sich ObservableCollection ändert

    Frage

  • Hallo ich habe ein DataGrid welches mit einer ObservableCollection verbunden ist. Nun möchte ich gern wenn sich die Liste über das Datagrid ändert. Eine Methode ausführen. Nur irgendwie komm ich nicht in das Set. 

    private ObservableCollection<Auto> _lAuto;
    public ObservableCollection<Auto> lAuto
            {
                get
                {
                    return _lAuto;
                }
                set
                {
                    if(_lAuto != value)
                    {
                        _lAuto = value;
                        NotifyPropertyChanged();
                        float p = 0;
                        foreach(Auto a in _lAuto)
                        {
                            p += a.Preis;
                        }
                    }
                }
            }

    <Window.DataContext>
            <main:AutoMain/>
        </Window.DataContext>
    
    <DataGrid ItemsSource="{Binding lAuto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

    Mittwoch, 11. Juli 2018 12:38

Antworten

  • Hi,

    das Verhalten der ObservableCollection ist normal an der Stelle (ich habe es zumindest noch nie anders festgestellt).

    Das CollectionChanged Event ist ganz nett, aber oft unzureichend weil das Event gefeuert wird, sobald du beginnst in der neuen Zeile im Datagrid zu schreiben.

    Ich nutze für derartige Fälle oft eine Erweiterung der ObservableCollection:

        /// <summary>
        /// Implements the "ItemPropertyChanged" Event for a ObservableCollection
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <seealso cref="System.Collections.ObjectModel.ObservableCollection{T}" />
        public sealed class TrulyObservableCollection<T> : ObservableCollection<T>
        where T : INotifyPropertyChanged
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="TrulyObservableCollection{T}"/> class.
            /// </summary>
            public TrulyObservableCollection()
            {
                CollectionChanged += FullObservableCollectionCollectionChanged;
            }
    
            /// <summary>
            /// Initializes a new instance of the <see cref="TrulyObservableCollection{T}"/> class.
            /// </summary>
            /// <param name="pItems">The p items.</param>
            public TrulyObservableCollection(IEnumerable<T> pItems) : this()
            {
                foreach (var item in pItems)
                {
                    this.Add(item);
                }
            }
    
            /// <summary>
            /// Fulls the observable collection collection changed.
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="e">The <see cref="NotifyCollectionChangedEventArgs"/> instance containing the event data.</param>
            private void FullObservableCollectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (e.NewItems != null)
                {
                    foreach (Object item in e.NewItems)
                    {
                        ((INotifyPropertyChanged)item).PropertyChanged += ItemPropertyChanged;
                    }
                }
                if (e.OldItems != null)
                {
                    foreach (Object item in e.OldItems)
                    {
                        ((INotifyPropertyChanged)item).PropertyChanged -= ItemPropertyChanged;
                    }
                }
            }
    
            /// <summary>
            /// Items the property changed.
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
            private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                NotifyCollectionChangedEventArgs args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, sender, sender, IndexOf((T)sender));
                OnCollectionChanged(args);
            }
        }

    Diese habe ich mal hier gefunden.

    Diese dann einfach Deklarieren:

    public TrulyObservableCollection<T> MyCollection { get; set; }

    Und im Constructor:

    MyCollection = new TrulyObservableCollection<T>();
    MyCollection.CollectionChanged += MyCollection_CollectionChanged;
    Das Event sieht dann so aus, welches etwas mehr liefert:

            private void DataG2_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (e.Action == NotifyCollectionChangedAction.Replace)
                {
                    ;
                }
                else if (e.Action == NotifyCollectionChangedAction.Add)
                {
                    ;
                }
                else if (e.Action == NotifyCollectionChangedAction.Move)
                {
                    ;
                }
                else if (e.Action == NotifyCollectionChangedAction.Remove)
                {
                    ;
                }
                else if (e.Action == NotifyCollectionChangedAction.Reset)
                {
                    ;
                }
            }

    "Replace" wird gefeuert, wenn du neue oder vorhandene Einträge editierst. Wenn du das DataGrid-Binding auf "UpdateSourceTrigger=LostFocus" stellst, wird das Event nur gefeuert, wenn du die Zeile verlässt.

    Gruß

    Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    • Als Antwort markiert MietzeTatze Donnerstag, 12. Juli 2018 12:57
    Mittwoch, 11. Juli 2018 20:06

Alle Antworten

  • Nur irgendwie komm ich nicht in das Set

    Hallo,

    was genau meinst Du damit?

    Sollte so eigentlich funktionieren, eine Alternative ist ObservableCollection.CollectionChanged Event


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Mittwoch, 11. Juli 2018 13:32
  • Dachte ich eigentlich auch nur wenn ich eine neuen Eintrag in das Datagrid mache löst es nicht das set aus. Ich schau mir mal dein Link mit den Event an. Aber vlt fällt jemand anderen noch was ein
    Mittwoch, 11. Juli 2018 14:07
  • Hi,

    das Verhalten der ObservableCollection ist normal an der Stelle (ich habe es zumindest noch nie anders festgestellt).

    Das CollectionChanged Event ist ganz nett, aber oft unzureichend weil das Event gefeuert wird, sobald du beginnst in der neuen Zeile im Datagrid zu schreiben.

    Ich nutze für derartige Fälle oft eine Erweiterung der ObservableCollection:

        /// <summary>
        /// Implements the "ItemPropertyChanged" Event for a ObservableCollection
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <seealso cref="System.Collections.ObjectModel.ObservableCollection{T}" />
        public sealed class TrulyObservableCollection<T> : ObservableCollection<T>
        where T : INotifyPropertyChanged
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="TrulyObservableCollection{T}"/> class.
            /// </summary>
            public TrulyObservableCollection()
            {
                CollectionChanged += FullObservableCollectionCollectionChanged;
            }
    
            /// <summary>
            /// Initializes a new instance of the <see cref="TrulyObservableCollection{T}"/> class.
            /// </summary>
            /// <param name="pItems">The p items.</param>
            public TrulyObservableCollection(IEnumerable<T> pItems) : this()
            {
                foreach (var item in pItems)
                {
                    this.Add(item);
                }
            }
    
            /// <summary>
            /// Fulls the observable collection collection changed.
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="e">The <see cref="NotifyCollectionChangedEventArgs"/> instance containing the event data.</param>
            private void FullObservableCollectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (e.NewItems != null)
                {
                    foreach (Object item in e.NewItems)
                    {
                        ((INotifyPropertyChanged)item).PropertyChanged += ItemPropertyChanged;
                    }
                }
                if (e.OldItems != null)
                {
                    foreach (Object item in e.OldItems)
                    {
                        ((INotifyPropertyChanged)item).PropertyChanged -= ItemPropertyChanged;
                    }
                }
            }
    
            /// <summary>
            /// Items the property changed.
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
            private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                NotifyCollectionChangedEventArgs args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, sender, sender, IndexOf((T)sender));
                OnCollectionChanged(args);
            }
        }

    Diese habe ich mal hier gefunden.

    Diese dann einfach Deklarieren:

    public TrulyObservableCollection<T> MyCollection { get; set; }

    Und im Constructor:

    MyCollection = new TrulyObservableCollection<T>();
    MyCollection.CollectionChanged += MyCollection_CollectionChanged;
    Das Event sieht dann so aus, welches etwas mehr liefert:

            private void DataG2_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                if (e.Action == NotifyCollectionChangedAction.Replace)
                {
                    ;
                }
                else if (e.Action == NotifyCollectionChangedAction.Add)
                {
                    ;
                }
                else if (e.Action == NotifyCollectionChangedAction.Move)
                {
                    ;
                }
                else if (e.Action == NotifyCollectionChangedAction.Remove)
                {
                    ;
                }
                else if (e.Action == NotifyCollectionChangedAction.Reset)
                {
                    ;
                }
            }

    "Replace" wird gefeuert, wenn du neue oder vorhandene Einträge editierst. Wenn du das DataGrid-Binding auf "UpdateSourceTrigger=LostFocus" stellst, wird das Event nur gefeuert, wenn du die Zeile verlässt.

    Gruß

    Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    • Als Antwort markiert MietzeTatze Donnerstag, 12. Juli 2018 12:57
    Mittwoch, 11. Juli 2018 20:06
  • Danke das ist echt super 
    Donnerstag, 12. Juli 2018 12:57
  • Hey ich habe es ausprobiert und es klappt super nochmal danke. Aber habe irgendwie ein Problem. Wenn ich Daten ins Datengrid eintrage. Wird kene neue Zeile zum eintragen bereitgestellt. Erst wenn ich das Datengrid nach einer Spalte zum Beispiel sortiere. Gibt es dazu auch eine Lösung?
    Dienstag, 17. Juli 2018 21:40
  • Im Normalfall wird eine neue Zeile bereitgestellt, sobald du die Zeile verlässt, die du gerade neu befüllt hast. Also zum Beispiel mit ENTER bestätigt hast oder durch einen KLICK auf eine andere Zeile...

    Das ist das normale Verhalten.

    Und das funktioniert bei dir nicht so?


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Mittwoch, 18. Juli 2018 05:41