更改属性值后重新建立 WPF 数据绑定

发布于 2024-09-24 10:04:51 字数 963 浏览 7 评论 0原文

我现在正在使用 ICollectionView,遇到一个问题,我认为我理解“为什么”,但不理解“如何修复它”。 :)

我有一个将数据绑定到 ICollectionView 的 ComboBox,它最初使用以下代码进行设置:

NameView = CollectionViewSource.GetDefaultView( names); // names is an IEnumerable<string> that comes from a LINQ query
NameView.CurrentChanged += new EventHandler(NameView_CurrentChanged);

一切正常,直到我执行一段生成新 IEnumerable 的代码并设置 NameView再次使用与上面相同的代码。一旦我这样做,CurrentItem就不再正常工作。

我之前在将 ObservableCollection 数据绑定到 ComboBoxes 时遇到过这个问题,并且通过使用 Clear()Add 解决了“解除绑定”问题() 而不是将 ObservableCollection 属性设置为新的 ObservableCollection

我的问题包括: 1. 如果我希望能够将属性设置为新集合,我可以以某种方式与新集合重新建立数据绑定吗?如果是这样,怎么办?如果不是,您能解释一下为什么这从根本上不可能吗? 2. 处理 ObservableCollectionICollectionView 中的更改的最佳方法是什么?我只清除和添加的方法是唯一的方法吗?

I'm playing with ICollectionView right now, and am encountering a problem where I think I understand the "why", but not the "how do I fix it". :)

I have a ComboBox that's databound to an ICollectionView, and it is initially set with the following code:

NameView = CollectionViewSource.GetDefaultView( names); // names is an IEnumerable<string> that comes from a LINQ query
NameView.CurrentChanged += new EventHandler(NameView_CurrentChanged);

Everything works great until I execute a piece of code that generates a new IEnumerable<string> and sets NameView again with the same code as above. Once I do this, CurrentItem is no longer working properly.

I've run into this problem before with ObservableCollection<string> databound to ComboBoxes, and I get around the "unbinding" problem by using Clear() and Add() instead of setting the ObservableCollection<string> property to a new ObservableCollection<string>.

My questions include:
1. If I wanted to be able to just set the property to a new collection, can I re-establish databinding with the new collection somehow? If so, how? If not, can you explain the WPFisms behind why this is fundamentally not possible?
2. What's the best way to deal with changes in an ObservableCollection<string> or ICollectionView? Is my approach of just Clearing and Adding the only way to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

阳光①夏 2024-10-01 10:04:51

当您将 WPF 控件绑定到 ICollectionViews 时(在使用 InitializeComponent 调用解析 XAML 时发生 - 您实际上应该在 XAML 中定义绑定!),控件会订阅集合发布的所需事件(例如 CollectionChanged)。

您的集合属性只是对内存地址的引用。当您将其弯曲到新集合(即新地址)时,数据绑定不会注意到。您不能指望原始集合会发布类似“IAmOuttaHere”的内容,并且显然控件不会听新集合说“我是新人”。但是如果我正确地看到这一点,您的代码片段除了向 CurrentChanged 添加一个事件处理程序之外什么也不做(这意味着您在选择组合框中的其他项目时进行观察)

绑定都是关于通知的,所以 - 只要您不告诉您的控制集合已被交换,它们将坚持初始集合。请尝试像这样实现 INotifyPropertyChanged:

    public class ViewModel : INotifyPropertyChanged
{
    private ICollectionView myCollection;

    public ICollectionView MyCollection
    {
        get
        {
            return this.myCollection;
        }
        set
        {
            this.myCollection = value;
            this.OnPropertyChanged("MyCollection");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public void ExchangeCollection()
    {
        this.MyCollection = new CollectionView(....)
    }

}

任何绑定都应该与 MyCollection 进行。虽然就我个人而言,我自己并没有定义 ICollectionViews,因为它们并不像漂亮的 IList 那样好用,而且一旦定义了绑定,它们就会自动包装在任何集合周围。

希望这对

塞比有帮助

When you bind your WPF Controls to ICollectionViews (Happens when the XAML is parsed withing your InitializeComponent-call - You should really define the bindings in XAML!), the Controls subscribe to the required events published by your collection (e.g. CollectionChanged).

Your collection property is just a reference to a memory address. When you bend this to a new collection (i.e. a new address), the DataBinding won't notice. You can't expect the original Collection to publish something like "IAmOuttaHere", and clearly the controls wouldn't listen to a new collection saying "I'm the new guy". But if I see this correctly, your snippet does nothing but add an eventhandler to the CurrentChanged (meaning your observe when some other item in the Combobox is being selected)

Binding is all about notification, so - as long as you don't tell your controls that the collection has been exchanged, they will stick to the initial collection. Please try to implement INotifyPropertyChanged like so:

    public class ViewModel : INotifyPropertyChanged
{
    private ICollectionView myCollection;

    public ICollectionView MyCollection
    {
        get
        {
            return this.myCollection;
        }
        set
        {
            this.myCollection = value;
            this.OnPropertyChanged("MyCollection");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public void ExchangeCollection()
    {
        this.MyCollection = new CollectionView(....)
    }

}

Any bindings should be made to MyCollection. Although, personally, I don't define ICollectionViews myself, since they are not really as nice to work with as for example a nifty IList and they are auto-wrapped around any collection anyway as soon as a binding is defined.

Hope this helps

Sebi

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文