【问题标题】:Uwp Combobox Binding Breaks on Source ChangeUwp 组合框绑定在源更改时中断
【发布时间】:2018-03-18 19:28:51
【问题描述】:

我在使用 MVVM 的 UWP 中遇到问题,我有一个 Combobox 和一个 ItemsSource 绑定到我的 ViewModel 中的项目集合,并且在我的 VM 中还有一个来自该集合的项目 @987654323 @ 绑定到。

我需要在我的视图模型中随意更改项目来源和选定项目。问题是,如果SelectedItem 在任何时间点都不存在于ItemsSource 中,则SelectedItem 的绑定似乎会永久中断。

示例: 假设我有一个绑定到我的 VM 的 Comobox:

<ComoboBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" />

现在在我的 ViewModel 中,我有:

public List<string> Items { get; set; } // Pretend these properties call on OnPropertyChanged
public string SelectedItem { get; set; }

public void Initialize() {
    Items = new List<string> { "A", "B", "C", "D" };
    SelectedItem = "B";
}

public void ChangeList() {
    // This breaks the binding that the Combobox has with SelectedItem
    Items = new List<string> { "E", "F", "G", "H" };

    // This does nothing on the XAML side as the binding is already broken by this poing
    SelectedItem = "H";
}

初始化时,应用程序将在选定的组合框中显示“B”。如果在代码中,比如说,我将其更改为“A”,那也将反映视图的变化。但是,当我调用 ChangeList() 时,组合框将设置为空白,并且将忽略我在后面的代码中所做的任何更改。

不幸的是,在我更新源列表之前将 SelectedItem 设置为 null 并不能解决我的问题。

我将如何更改 VM 中的源和选定项?

【问题讨论】:

  • 同样的问题发生在 WPF 中。
  • 基于侧边栏中的其他几个答案,我认为解决此问题的唯一方法是编写一个重新实现 SelectedItem 的包装器对象(可能还有其他几个属性) .这感觉就像控件中的一个错误,它没有使用正确的方法来更新属性值。 (我开始走这条路,然后才发现我的问题是当列表被清除时空字符串会破坏绑定,但空字符串不会。)

标签: c# xaml mvvm combobox uwp


【解决方案1】:

当您将Items 更改为新集合时,ComboBox 应为您自动重置SelectedItem。您将需要收到此更改并回复 NotifyPropertyChanged

尝试将绑定更改为双向:

<ComoboBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />

【讨论】:

  • 我同意它应该像那样工作。我观察到,当我将绑定模式设置为 TwoWay 时,SelectedItem 被设置为 null,但之后绑定似乎仍然中断。更改数据模型中的项目不再触发组合框上的 get 并且不会选择任何内容。
【解决方案2】:

使用 ObservableCollection 而不是 List

公共字符串 SelectedItem { get;放; }

    private ObservableCollection<string> _Items = new ObservableCollection<string> { "A","B", "C"};
    public ObservableCollection<string> Items
    {
        get
        {
            return _Items;
        }

        set
        {
            if (value == _Items)
            { return; }
            _Items = value;
            RaisePropertyChanged(nameof(Items));
        }
    }

好的,我不确定您的代码是什么样的,但是如果您要替换 ComboBox 的 ItemsSource,那么您可以这样做:

Items.Clear();

Items = new ObservableCollection{ "D","E", "F"};

SelectedItem =Items.FirstOrDefault (c => c == "D");

您必须自己进行错误检查,通过执行 Items.Any( c => c == "D"); 来查看集合中是否存在“D”这将返回真或假。如果它返回 true 然后继续设置您的选定项: SelectedItem =Items.FirstOrDefault (c => c == "D");

现在请记住,“D”可以是任何字符串。 字符串搜索字符串 = "";

所以现在您可以像这样填写 Lambda 语句: SelectedItem =Items.FirstOrDefault ( c => c == searchString);

希望对您有所帮助。

【讨论】:

  • 不幸的是,这并不能解决问题。我没有添加/删除源中的项目,而是用新列表替换它。这会导致当前的SelectedItem 不再存在于列表中,这就是我认为破坏绑定的原因
  • 好的,不确定您的代码到底是什么样的,但如果您删除 ItemSource,您将不得不在 ObservableCollection 中查找该项目。所以,我要做的就是这样做:
  • 至少在 WPF 中,集合是否为ObservableCollection 并不重要。
  • 是的,但不幸的是在 UWP 中它确实很重要:/
  • 我的意思是消极的:我对 WPF 的体验是,更改为 ObservableCollection 并不会消除这种行为。
猜你喜欢
  • 1970-01-01
  • 2021-07-23
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
  • 2023-04-04
  • 2017-10-23
  • 2016-02-22
相关资源
最近更新 更多