Silverlight 如何从包含的对象正确触发CollectionChanged通知?
这是对本质上是一个简单问题的冗长解释。我使用的是Telerilk RadDropDownButton,它显示带有复选框的列表项Silverlight 如何从包含的对象正确触发CollectionChanged通知?,silverlight,observablecollection,Silverlight,Observablecollection,这是对本质上是一个简单问题的冗长解释。我使用的是Telerilk RadDropDownButton,它显示带有复选框的列表项 <Controls:RadDropDownButton AutoOpenDelay="0:0:0.0" x:Name="Urgency" VerticalAlignment="Center" Width="150" Content="{Binding Path=ItemsSource, ElementName=Urgency
<Controls:RadDropDownButton AutoOpenDelay="0:0:0.0" x:Name="Urgency" VerticalAlignment="Center" Width="150" Content="{Binding Path=ItemsSource, ElementName=UrgencyList, Mode=TwoWay, Converter={StaticResource ButtonTextConverter}}" HorizontalContentAlignment="Left">
<Controls:RadDropDownButton.DropDownContent>
<ListBox x:Name="UrgencyList">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Content="{Binding Name}" ClickMode="Press" IsChecked="{Binding IsChecked, Mode=TwoWay}" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Controls:RadDropDownButton.DropDownContent>
</Controls:RadDropDownButton>
我将列表框绑定到代码背后的数据,如下所示:
private void SearchParamsVertical_Loaded(object sender, RoutedEventArgs e)
{
urgencyList = new ObservableCollection<UrgencyItem>
{
new UrgencyItem {ID = 1, IsChecked = false, Name = "Non Emergent"},
new UrgencyItem {ID = 2, IsChecked = false, Name = "Emergent"},
new UrgencyItem {ID = 3, IsChecked = false, Name = "Stat Emergent"},
new UrgencyItem {ID = 4, IsChecked = false, Name = "Stroke Protocol"}
};
urgencyList.CollectionChanged += urgencyList_CollectionChanged;
UrgencyList.ItemsSource = urgencyList;
}
private void SearchParamsVertical\u已加载(对象发送方,路由目标e)
{
urgencyList=新的可观察集合
{
new UrgencyItem{ID=1,IsChecked=false,Name=“非紧急”},
new UrgencyItem{ID=2,IsChecked=false,Name=“Emergent”},
new UrgencyItem{ID=3,IsChecked=false,Name=“Stat Emergent”},
新建UrgencyItem{ID=4,IsChecked=false,Name=“Stroke Protocol”}
};
urgencyList.CollectionChanged+=urgencyList\u CollectionChanged;
UrgencyList.ItemsSource=UrgencyList;
}
问题就出在这里……
选中复选框后,内容的值应更新。事实并非如此
之所以不是,是因为,尽管通知触发了IsChecked已更改,但该通知基本上没有任何进展。UrgencyItem对象不知道它是ObservableCollection的一部分。关于ObservableCollection,它只在向集合中添加/删除项时向其绑定发送通知。换句话说,更改集合中项目的属性不会触发CollectionChanged事件,因为未添加/删除任何对象
我需要做的是在修改集合的属性时触发collectionChanged事件。我以前知道怎么做,但是离开Silverlight太久了,我已经忘记怎么做了
有人吗 简而言之,我认为您的诊断是正确的:如果ObservableCollection中的某个对象发生更改,您通常不会收到CollectionChanged通知,即使该对象实现了INotifyPropertyChanged。就我所知,没有一种简单的方法可以通过内置的Silverlight类获得您想要的行为 我知道有三种可能的解决方法: (1) 一个选项是为urgencyList创建自己的集合,该集合继承自ObservableCollection,实现此行为,即,它订阅添加到集合中的每个对象的INPC通知,并在发生此情况时触发CollectionChanged事件 (2) 第二种选择是使用类似的东西,它有自己的ReactiveCollection来实现此行为
(3) 第三种选择是通过以下方式创建您的urgencyList。它们返回的集合会自动实现此行为。简而言之,我认为您的诊断是正确的:如果ObservableCollection中的对象发生更改,您通常不会收到CollectionChanged通知,即使该对象实现了INotifyPropertyChanged。就我所知,没有一种简单的方法可以通过内置的Silverlight类获得您想要的行为 我知道有三种可能的解决方法: (1) 一个选项是为urgencyList创建自己的集合,该集合继承自ObservableCollection,实现此行为,即,它订阅添加到集合中的每个对象的INPC通知,并在发生此情况时触发CollectionChanged事件 (2) 第二种选择是使用类似的东西,它有自己的ReactiveCollection来实现此行为
(3) 第三种选择是通过以下方式创建您的urgencyList。它们返回的集合自动实现此行为。这就是我正在使用的。Ken在nr(1)中的建议,我认为:
public class Person: INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set {
_name = value;
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
我在plobservatablenotifylist
中有这些对象,我在ItemsControl
上将其设置为ItemsSource
。A只要我更新了值(使用setter),绑定就会自动更新
public class PLObservableNotifyList<T> :
ObservableCollection<T> where T : INotifyPropertyChanged
{
public ItemPropertyChangedEventHandler ItemPropertyChanged;
public EventHandler CollectionCleared;
protected override void OnCollectionChanged(
NotifyCollectionChangedEventArgs args)
{
base.OnCollectionChanged(args);
if (args.NewItems != null)
foreach (INotifyPropertyChanged item in args.NewItems)
item.PropertyChanged += OnItemPropertyChanged;
if (args.OldItems != null)
foreach (INotifyPropertyChanged item in args.OldItems)
item.PropertyChanged -= OnItemPropertyChanged;
}
void OnItemPropertyChanged(object sender,
PropertyChangedEventArgs args)
{
if (ItemPropertyChanged != null)
ItemPropertyChanged(this,
new PLItemPropertyChangedEventArgs(sender,
args.PropertyName));
}
protected override void ClearItems()
{
foreach (INotifyPropertyChanged item in Items)
item.PropertyChanged -= OnItemPropertyChanged;
if (CollectionCleared != null)
CollectionCleared(this, EventArgs.Empty);
base.ClearItems();
}
}
公共类PLObservableNotifyList:
可观察到的集合,其中T:InotifyProperty已更改
{
public ItemPropertyChangedEventHandler ItemPropertyChanged;
公共事件处理程序集合已清除;
CollectionChanged上的受保护覆盖无效(
NotifyCollectionChangedEventArgs(参数)
{
基础.更改的集合(args);
如果(args.NewItems!=null)
foreach(args.NewItems中的INotifyPropertyChanged项)
item.PropertyChanged+=OnItemPropertyChanged;
如果(args.OldItems!=null)
foreach(args.OldItems中的INotifyPropertyChanged项)
item.PropertyChanged-=OnItemPropertyChanged;
}
无效OnItemPropertyChanged(对象发送方,
PropertyChangedEventArgs(参数)
{
if(ItemPropertyChanged!=null)
ItemPropertyChanged(此,
新PLITEMPROPERTYCHANGDEVENTARGS(发送方,
args.PropertyName));
}
受保护的覆盖无效ClearItems()
{
foreach(项目中的INotifyPropertyChanged项目)
item.PropertyChanged-=OnItemPropertyChanged;
如果(CollectionCleared!=null)
CollectionCleared(此为EventArgs.Empty);
base.ClearItems();
}
}
这就是我正在使用的。Ken在nr(1)中的建议,我认为:
public class Person: INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set {
_name = value;
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
我在plobservatablenotifylist
中有这些对象,我在ItemsControl
上将其设置为ItemsSource
。A只要我更新了值(使用setter),绑定就会自动更新
public class PLObservableNotifyList<T> :
ObservableCollection<T> where T : INotifyPropertyChanged
{
public ItemPropertyChangedEventHandler ItemPropertyChanged;
public EventHandler CollectionCleared;
protected override void OnCollectionChanged(
NotifyCollectionChangedEventArgs args)
{
base.OnCollectionChanged(args);
if (args.NewItems != null)
foreach (INotifyPropertyChanged item in args.NewItems)
item.PropertyChanged += OnItemPropertyChanged;
if (args.OldItems != null)
foreach (INotifyPropertyChanged item in args.OldItems)
item.PropertyChanged -= OnItemPropertyChanged;
}
void OnItemPropertyChanged(object sender,
PropertyChangedEventArgs args)
{
if (ItemPropertyChanged != null)
ItemPropertyChanged(this,
new PLItemPropertyChangedEventArgs(sender,
args.PropertyName));
}
protected override void ClearItems()
{
foreach (INotifyPropertyChanged item in Items)
item.PropertyChanged -= OnItemPropertyChanged;
if (CollectionCleared != null)
CollectionCleared(this, EventArgs.Empty);
base.ClearItems();
}
}
公共类PLObservableNotifyList:
可观察到的集合,其中T:InotifyProperty已更改
{
公共项目属性ChangedEventHandler ItemPro