Benachrichtigen Sie ObservableCollection, wenn sich der Artikel ändert
Fand ich auf diesem link
ObservableCollection nicht bemerken, wenn das Objekt ändert (auch mit INotifyPropertyChanged)
einige Techniken, um Benachrichtigen einer Observablecollection, dass ein Element geändert wurde. die TrulyObservableCollection in diesem link scheint das zu sein was ich Suche.
public class TrulyObservableCollection<T> : ObservableCollection<T>
where T : INotifyPropertyChanged
{
public TrulyObservableCollection()
: base()
{
CollectionChanged += new NotifyCollectionChangedEventHandler(TrulyObservableCollection_CollectionChanged);
}
void TrulyObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Object item in e.NewItems)
{
(item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
}
}
if (e.OldItems != null)
{
foreach (Object item in e.OldItems)
{
(item as INotifyPropertyChanged).PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);
}
}
}
void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
NotifyCollectionChangedEventArgs a = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
OnCollectionChanged(a);
}
}
Aber wenn ich versuche, es zu benutzen, bekomme ich keine Benachrichtigungen über die Sammlung. Ich bin mir nicht sicher, wie Sie Sie richtig zu implementieren, das in meinem C# - Code:
XAML :
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding MyItemsSource, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
</DataGrid>
ViewModel :
public class MyViewModel : ViewModelBase
{
private TrulyObservableCollection<MyType> myItemsSource;
public TrulyObservableCollection<MyType> MyItemsSource
{
get { return myItemsSource; }
set
{
myItemsSource = value;
//Code to trig on item change...
RaisePropertyChangedEvent("MyItemsSource");
}
}
public MyViewModel()
{
MyItemsSource = new TrulyObservableCollection<MyType>()
{
new MyType() { MyProperty = false },
new MyType() { MyProperty = true },
new MyType() { MyProperty = false }
};
}
}
public class MyType : ViewModelBase
{
private bool myProperty;
public bool MyProperty
{
get { return myProperty; }
set
{
myProperty = value;
RaisePropertyChangedEvent("MyProperty");
}
}
}
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChangedEvent(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
PropertyChanged(this, e);
}
}
}
Wenn ich das Programm starte, habe ich die 3 Kontrollkästchen auf false, true, false, wie in der property-Initialisierung.
aber wenn ich den Zustand einer der ckeckbox, das Programm Durchlaufen item_PropertyChanged aber nie in MyItemsSource Eigentums.
InformationsquelleAutor der Frage Pansoul | 2011-12-13
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Stelle, die Sie kommentiert haben, wie
//Code to trig on item change...
wird nur ausgelöst, wenn das collection-Objekt verändert wird, wie wenn es festgelegt wird, um ein neues Objekt oder auf null gesetzt.Mit Ihrem aktuellen Implementierung von TrulyObservableCollection, mit der Eigenschaft verändert Ereignisse in Ihre Sammlung, Registrierung etwas
CollectionChanged
FalleMyItemsSource
Ich persönlich wirklich nicht mag, diese Umsetzung. Sie heben eine
CollectionChanged
Fall, dass sagt, dass die gesamte Kollektion zurückgesetzt wurde, können Sie jederzeit eine Eigenschaft ändert. Sicher werde es so machen, das UI-update, wenn ein Element in der Sammlung änderungen, aber ich sehe, dass das schlecht auf die Leistung, und es scheint nicht, einen Weg zu haben, zu identifizieren, welche Eigenschaft geändert hat, die ist eines der wichtigsten Stücke von Informationen, die ich benötigen in der Regel, wenn etwasPropertyChanged
.Ich lieber mit einem normalen
ObservableCollection
und nur anschließen diePropertyChanged
Ereignisse Gegenstände aufCollectionChanged
. Die Bereitstellung der Benutzeroberfläche gebunden ist, richtig, um die Elemente in derObservableCollection
sollten Sie nicht brauchen, zu sagen, die Benutzeroberfläche zu aktualisieren, wenn eine Eigenschaft auf ein Element in der Sammlung änderungen.InformationsquelleAutor der Antwort Rachel
Ich gelöst, in diesem Fall durch die Verwendung statischer Aktion
InformationsquelleAutor der Antwort sat1582
Den
ObservableCollection
und seine Derivate wirft seine Eigenschaft ändert, intern. Den code in Ihre setter sollte nur ausgelöst werden, wenn Sie zuweisen eine neueTrulyObservableCollection<MyType>
zu denMyItemsSource
Eigenschaft. Das heißt, es sollte nur einmal geschehen, aus dem Konstruktor.Ab diesem Zeitpunkt, erhalten Sie die Eigenschaft ändern-Meldungen aus der collection, nicht von dem setter in der viewmodel.
InformationsquelleAutor der Antwort Jay
Ich weiß, es ist spät, aber vielleicht hilft das auch anderen. Ich habe eine Klasse angelegt
NotifyObservableCollection
das löst das problem der fehlenden Benachrichtigung an die Sache selbst, als eine Eigenschaft des Elements ändert. Die Nutzung ist so einfach wieObservableCollection
.Während Elemente Hinzugefügt oder entfernt die Klasse leitet die Elemente
PropertyChanged
event zu den SammlungenPropertyChanged
Veranstaltung.Verwendung:
Wenn nun eine Eigenschaft eines Elements in
DataItems
verpasst, der folgende xaml-Code wird eine Benachrichtigung erhalten, wenn es bindet anParameters[0]
oder der Sache selbst mit Ausnahme der sich ändernden EigenschaftValue
des Elements (Konverter an Trigger aufgerufen wird zuverlässig bei jeder änderung).InformationsquelleAutor der Antwort WPFGermany
Könnten Sie eine Erweiterung Methode, um benachrichtigt zu werden, über die änderung der Eigenschaft eines Elements in einer collection in einer generischen Art und Weise.
InformationsquelleAutor der Antwort Mike de Klerk
Alle Lösungen, die hier richtig sind,aber Ihnen fehlt ein wichtiges Szenario, in dem die Methode Klar() verwendet wird, die nicht
OldItems
imNotifyCollectionChangedEventArgs
Objekt.dies ist der perfekte
ObservableCollection
.Können Sie sogar gehen die extra Meile, und ändern Sie die ItemPropertyChanged zu bieten, die Liste Besitzer, wie dieser
Außerhalb der Klasse in einigen namespace :
public delegate void ListedItemPropertyChangedEventHandler(IList SourceList, object Item, PropertyChangedEventArgs e);
in der Klasse ändern Sie diese :
InformationsquelleAutor der Antwort bigworld12
Eine einfache Lösung ist die Verwendung
BindingList<T>
stattObservableCollection<T>
. In der Tat die BindingList relay item-Benachrichtigungen ändern. So eine verbindliche Liste, falls das Element implementiert die SchnittstelleINotifyPropertyChanged
dann können Sie einfach Holen Sie sich Benachrichtigungen über das ListChanged-Ereignis.Siehe auch diese SO beantworten.
InformationsquelleAutor der Antwort Malick