Silverlight 如何从包含的对象正确触发CollectionChanged通知?

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

这是对本质上是一个简单问题的冗长解释。我使用的是Telerilk RadDropDownButton,它显示带有复选框的列表项

                    <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