Уведомление об изменении свойства в словаре
19143 просмотра
5 ответа
У меня есть форма WPF / XAML, связанная со свойством в словаре, похожая на эту:
<TextBox Text="{Binding Path=Seat[2B].Name}">
Seat
выставляется как объект IDictionary<String, Reservation>
на объекте самолета.
class airplane
{
private IDictionary<String, Reservation> seats;
public IDictionary<String, Reservation> Seat
{
get { return seats; }
// set is not allowed
}
}
В коде моего окна значение места 2B иногда изменяется, и после этого я хочу уведомить пользовательский интерфейс о том, что свойство изменилось.
class MyWindow : Window
{
private void AddReservation_Click(object sender, EventArgs e)
{
airplane.Seat["2B"] = new Reservation();
// I want to override the assignment operator (=)
// of the Seat-dictionary, so that the airplane will call OnNotifyPropertyChanged.
}
}
Я посмотрел, есть ли Словарь IObservable
, чтобы я мог наблюдать за изменениями в нем, но это не так.
Есть ли хороший способ «поймать» изменения в словаре в самолетном классе, чтобы я мог NotifyPropertyChanged
.
Ответы (5)
13 плюса
Доктор WPF создал ObservableDictionary
по этой ссылке: http://drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/
Обновление: комментарий, сделанный доктором WPF по следующей ссылке, говорит, что он сам исправил эту проблему, поэтому больше не нужно вносить следующие изменения
Также по этой ссылке было сделано дополнение: http://10rem.net/blog/2010/03/08/binding-to-a-dictionary-in-wpf-and-silverlight
Небольшое изменение было
// old version
public TValue this[TKey key]
{
get { return (TValue)_keyedEntryCollection[key].Value; }
set { DoSetEntry(key, value);}
}
// new version
public TValue this[TKey key]
{
get { return (TValue)_keyedEntryCollection[key].Value; }
set
{
DoSetEntry(key, value);
OnPropertyChanged(Binding.IndexerName);
}
}
Автор: Fredrik Hedblad
Размещён: 11.02.2011 01:49
4 плюса
Вы можете просто создать класс, который реализует интерфейс INotifyPropertyChanged, обернуть ваше значение этим классом и использовать его в словаре. У меня была похожая проблема, и я сделал следующее:
class Parameter : INotifyPropertyChanged //wrapper
{
private string _Value;
public string Value //real value
{
get { return _Value; }
set { _Value = value; RaisePropertyChanged("Value"); }
}
public Parameter(string value)
{
Value = value;
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class ViewModel
{
public Dictionary<string, Parameter> Parameters
}
<ItemsControl ItemsSource="{Binding Path=Parameters, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Margin="3" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding Path=Key}" Margin="3" />
<TextBox Grid.Column="1" Text="{Binding Path=Value.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True" Margin="3" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
После этого, если вы измените значения в словаре, вы увидите изменения в пользовательском интерфейсе.
Автор: Paval Размещён: 07.02.2014 05:142 плюса
Вам нужно иметь четкое представление о том, что вы пытаетесь выполнить, прежде чем приступить к реализации уведомлений об изменениях. Если вы хотите, чтобы пользовательский интерфейс обновлялся при изменении объекта, сохраненного в словаре с данным ключом, это одно. Если вы хотите, чтобы пользовательский интерфейс обновлялся при изменении свойства объекта, хранящегося в словаре, это совсем другое дело.
Другими словами, если вы хотите, чтобы пользовательский интерфейс обновлялся при Reservation.Name
изменениях, вам нужен Reservation
объект для выполнения уведомлений об изменениях. Если вы хотите, чтобы пользовательский интерфейс обновлялся, когда Seat[2B]
задано другое значение Reservation
, то словарь должен будет выполнить уведомление об изменении.
1 плюс
Один из способов обойти это, вероятно, заключался бы в инкапсуляции словаря, тогда вы можете реализовать уведомляющие интерфейсы и контролировать доступ к словарю, т.е. если кто-то использует скобки для установки значения, вы можете установить значение внутреннего словаря и поднять уведомление.
Автор: H.B. Размещён: 11.02.2011 01:301 плюс
Вы всегда можете получить из словаря (или IDictionary), чтобы создать ObservableDictionary:
public class ObservableDictionary<TKey, TVal>:IDictionary<TKey, TVal>, IObservable
{
private Dictionary<TKey, TVal> _data;
//Implement IDictionary, using _data for storage and raising NotifyPropertyChanged
}
Самая большая проблема, с которой вы, вероятно, столкнетесь, заключается в том, что вы не сможете непосредственно обнаружить изменение значения; только добавление и удаление KVP. Для этого измените _data на a List<ObservableKeyValuePair>
, реализуйте там также IObservable и прикрепите обработчик к каждому новому создаваемому или полученному элементу, который будет реагировать на NotifyPropertyChanged KVP и вызовет NotifyValueChanged вашего родительского класса.
Вопросы из категории :
- c# Преобразовать десятичную в двойную?
- c# Как рассчитать чей-то возраст в C #?
- c# Как вы сортируете словарь по значению?
- c# В чем разница между int и Integer в Java и C #?
- c# Как создать новый экземпляр объекта из Типа
- c# Datatable против Dataset
- wpf Предотвращение утечек памяти с прикрепленным поведением
- wpf Как правильно создать приложение WPF с одним экземпляром?
- wpf Богатый GUI OS X Frameworks?
- wpf Как проверить пользовательский интерфейс WPF?
- wpf Связывание свойства enum с ComboBox в WPF
- wpf Требуется ли знание смеси?
- data-binding Общие реализации IBindingListView
- data-binding Лучший способ заставить данные, связанные с WPF ListBox, обновить?
- data-binding WPF CommandParameter имеет значение NULL при первом вызове CanExecute
- data-binding Richtextbox wpf привязка
- data-binding Как установить цвет фона на основе свойства bool в WPF
- data-binding Связывание ListView с свойством «IsSelected» ListViewItem