[英]Notify Property Changed on a Dictionary
我有一个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的值,之后,我想通知UI该属性已更改。
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.
}
}
我已经看过Dictionary是否是IObservable
,所以我可以观察它的变化,但它似乎不是。
有没有什么好方法可以“抓住”飞机类中字典的更改,以便我可以NotifyPropertyChanged
。
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);
}
}
您可以创建一个实现INotifyPropertyChanged接口的类,通过此类包装您的值并在Dictionary中使用它。 我遇到了类似的问题并做了下一步:
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>
之后,如果更改字典中的值,您将看到UI中的更改。
在开始实施更改通知之前,您需要清楚地了解您要完成的任务。 如果您希望在存储在具有给定键的字典中的对象发生更改时更新UI,则这是一回事。 如果您希望在存储在字典中的对象的属性发生更改时更新UI,那完全是另一回事。
换句话说,如果您希望在Reservation.Name
更改时更新UI,则需要Reservation
对象来执行更改通知。 如果您希望在将Seat[2B]
设置为其他Reservation
时更新UI,则字典将需要执行更改通知。
解决此问题的一种方法可能是封装字典,然后您可以实现通知接口并控制对字典的访问,即如果有人使用括号设置值,您可以设置内部字典的值并提高通知。
您总是可以从Dictionary(或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更改为List<ObservableKeyValuePair>
,同时在那里实现IObservable,并将处理程序附加到您创建或接收的每个新元素,这些元素将响应KVP的NotifyPropertyChanged并引发父类的NotifyValueChanged。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.