Так как я часами работаю над очень сложной проблемой:
Какова DataGrid , которая связана с ObservableCollection правильно , обновлена , когда другая ObservableCollection, которая находится внутри ObservableCollection DataGrid связан с изменениями?
Пока DataGrid обновляется только когда я щелкаю по соответствующей ячейке.
Я подготовил полный пример исходного кода, чтобы проиллюстрировать следующую (очень простую) ситуацию:
Существует ViewModel, которая содержит список. Этот список является ObservableCollection и содержит две вещи: целое число и другой список (снова ObservableCollection), который содержит четыре целых числа.
Затем существует DataGrid, который имеет два столбца. Один столбец для целого числа и один столбец для списка целых чисел.
Это маленькое приложение имеет кнопки для изменения целых чисел во вложенном списке, то есть добавления +1 к одному из четырех целых чисел.
GOAL заключается в том, что изменение вложенного списка отражается в DataGrid.
Пока что ПРОБЛЕМА состоит в том, что это происходит только с внешним триггером (например, щелчок по соответствующей ячейке или щелчок по заголовку одного столбца, который сортирует столбец и т. Д.)
Итак, вот полный код:
Это код ViewModel, к которому привязана DataGrid:
public class ViewModel: INotifyPropertyChanged {
private Items items;
public Items Items {
get { return items; }
set {
items = value;
firePropertyChanged("Items");
}
}
public ViewModel() {
Items = new Items();
}
private void firePropertyChanged(string property) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class Items: ObservableCollection<Item> {
public Items()
: base() {
this.CollectionChanged += new NotifyCollectionChangedEventHandler(OnCollectionChanged);
}
private void OnCollectionChanged(object o, 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);
}
}
public class List: ObservableCollection<NumberItem> {
public List()
: base() {
this.CollectionChanged += new NotifyCollectionChangedEventHandler(OnCollectionChanged);
}
private void OnCollectionChanged(object o, 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);
}
}
public class NumberItem : INotifyPropertyChanged {
private int number;
public int Number {
get { return number; }
set {
number = value;
firePropertyChanged("Number");
}
}
public NumberItem(int i) {
Number = i;
}
private void firePropertyChanged(string property) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class Item : INotifyPropertyChanged {
private List list;
public List List {
get { return list; }
set {
list = value;
firePropertyChanged("List");
}
}
private int numberOne;
public int NumberOne {
get { return numberOne; }
set {
numberOne = value;
firePropertyChanged("NumberOne");
}
}
private void firePropertyChanged(string property) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
/// <summary>
/// This converter simply transforms the list of integers into a string.
/// </summary>
public class Converter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
List l = (List)value;
string s = "";
return s + l[0].Number + " " + l[1].Number + " " + l[2].Number + " " + l[3].Number;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
return null;
}
}
Код кнопок, управляющих целыми числами во вложенном списке, следующий:
private void plus1L(object sender, RoutedEventArgs e) {
vm.Items[0].List[0].Number += 1;
}
И, наконец, это XAML, где DataGrid становится связанным:
<sdk:DataGrid x:Name="dg" Margin="17,139,21,0" ItemsSource="{Binding Items}" AutoGenerateColumns="False" VerticalAlignment="Top" Height="164" d:LayoutOverrides="Width, HorizontalMargin">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn x:Name="A" Header="A" Binding="{Binding NumberOne}"/>
<sdk:DataGridTextColumn x:Name="List" Header="List" Binding="{Binding List, Converter={StaticResource Converter}}"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>*emphasized text*