更新未实现IObservable集合的绑定

时间:2009-05-11 21:08:59

标签: wpf data-binding

我正在尝试将列表框绑定到集合。问题是集合可以更改,但集合不实现IObservableCollection。强制绑定刷新的最佳方法是什么?

4 个答案:

答案 0 :(得分:1)

如果没有关于如何以及在何处使用此集合的更多信息,以下是一些可能对您有帮助的指示。

  • 如果集合未密封,您可以继承它。
  • 如果集合是密封的,您可以创建一个包含集合实例的适配器类,并包装所有相关方法。

在任何情况下,您的新类都可以实现IObservableCollection并用于绑定。

答案 1 :(得分:1)

正如Tormod所建议的那样,最好的方法是将集合更改为ObservableCollection,或者在集合中实现INotifyCollectionChanged将负责刷新UI。

但是,如果这些选项不可用,那么您可以通过在包含该集合的任何类中使用INotifyPropertyChanged来“强制”刷新。然后,我们将像常规属性一样处理列表,并使用setter通知更改。要做到这一点,它需要重新分配引用,这就是为什么首选使用像ObservableCollection这样的东西,以及引发PropertyChanged事件。

以下是一个快速示例,展示了如何只使用标准通用List:

public partial class Window1 : Window, INotifyPropertyChanged
{
    public Window1()
    {
        InitializeComponent();
        this.Names = new List<string>() { "Mike", "Robert" };
        this.DataContext = this;
    }

    private IList<string> myNames;
    public IList<string> Names
    {
        get
        {
            return this.myNames;
        }
        set
        {
            this.myNames = value;
            this.NotifyPropertyChanged("Names");
        }
    }

    private void OnAddName(object sender, RoutedEventArgs e)
    {
        Names.Add("Kevin");
        Names = Names.ToList();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

的Xaml:

<Window x:Class="Sample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1"
    Height="300"
    Width="300">
<Grid>
    <StackPanel>
        <ListBox ItemsSource="{Binding Names}" />
        <Button Content="Add Name"
                Click="OnAddName" />
    </StackPanel>
</Grid>

答案 2 :(得分:0)

您可以将绑定设置为显式更新,然后通过代码刷新按钮来触发更新。

作为一个例子。

<StackPanel>
    <ListBox 
        x:Name="lb" 
        ItemsSource="{Binding SomeList, UpdateSourceTrigger=Explicit}" 
        />
    <Button Content="Refresh" Click="Refresh_Click" />
</StackPanel>

private void Refresh_Click(object sender, RoutedEventArgs e)
{
    BindingExpression be = lb.GetBindingExpression(ListBox.ItemsSourceProperty);
    be.UpdateSource();
}

答案 3 :(得分:0)

您还可以在ViewModel中强制刷新。这是我见过Josh Smith在他的MVVM演示应用程序中做的事情:

ICollectionView coll = CollectionViewSource.GetDefaultView(myCollection);
if (coll!=null)
   coll.Refresh();

myCollection可以是您绑定到View的任何类型的集合。

Bea Stollnitz有关于CollectionViewSource的更多信息: http://www.beacosta.com/blog/?m=200608