为什么 WPF 组合框不能正确反映绑定值

本文关键字:绑定 WPF 组合 不能 为什么 | 更新日期: 2023-09-27 18:30:44

我有一个组合框,其属性ItemsSource和SelectedValue绑定到模型。有时,模型需要将所选项目调整为不同的项目,但是当我在模型中执行此操作时,模型值不会反映在视图中,即使正确设置了 SelectedValue(使用 snoop 和 SelectionChanged 事件处理程序进行检查)。

为了说明这个问题,这里有一个简单的 xaml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
      <ComboBox Height="25" Width="120" SelectedValue="{Binding SelectedValue}" SelectedValuePath="Key" ItemsSource="{Binding PossibleValues}" DisplayMemberPath="Value"/>
   </Grid>
</Window>

这是模型:

using System.Collections.Generic;
using System.Windows;
using System.ComponentModel;
namespace WpfApplication1
{
   public partial class MainWindow : Window, INotifyPropertyChanged
   {
      int m_selectedValue = 2;
      Dictionary<int, string> m_possibleValues = new Dictionary<int, string>() { { 1, "one" }, { 2, "two" }, { 3, "three" }, {4,"four"} };
      public int SelectedValue
      {
         get { return m_selectedValue; }
         set 
         {
            if (value == 3)
            {
               m_selectedValue = 1;
            }
            else
            {
               m_selectedValue = value;
            }
            PropertyChanged(this, new PropertyChangedEventArgs("SelectedValue"));
         }
      }
      public Dictionary<int, string> PossibleValues
      {
         get { return m_possibleValues; }
         set { m_possibleValues = value; }
      }

      public MainWindow()
      {
         InitializeComponent();
      }
      public event PropertyChangedEventHandler PropertyChanged;
   }
}

我预计行为如下:

  1. 最初,选择两个
  2. 选择"一"->组合框显示"一"
  3. 选择"两个"->组合框显示"两个"
  4. 选择"三个"->组合框显示""
  5. 选择"四"->组合框显示"四"

但是,在#4中,显示了"三"。为什么?模型中的值已更改为 1("一"),但视图仍显示 3("三")。

我通过在 SelectionChanged 事件处理程序中显式更新绑定目标找到了解决方法,但这似乎是错误的。有没有其他方法可以实现这一目标?

为什么 WPF 组合框不能正确反映绑定值

选择项时,绑定引擎将更新模型,并忽略在调用属性 setter 期间刚刚更改的属性的任何PropertyChanged。如果不这样做,事情可能会进入无限循环。

系统假定资源库不会更改它传递的值。此处的解决方法很简单:在绑定上使用Dispatcher.BeginInvoke()或设置IsAsync=True来获取要查找的行为。但是,我个人强烈建议您不要这样做。不仅因为它引入了一大堆与时间相关的新问题,而且主要是因为它是解决一个本来就不应该存在的问题的解决方法。

干脆不要这样做。它不仅适用于 WPF:任何更改资源库的人都可以期望它刚刚设置的值被正确设置,而不会引发异常。更改二传手内部的值是违反直觉的,以后可能会咬你。此外,对于应用程序的用户来说,看到组合框忽略其选择可能会非常令人不安。

如果不喜欢传递的值,请引发异常并使用Binding.ValidatesOnExceptions告诉 WPF 这是预期的。如果不希望用户选择此值,请不要首先将其放在列表中。如果由于其他业务规则,该项不应有条件地可用,请动态筛选列表或应用触发器。

我在绑定到ComboBox控件的SelectedValue和/或SelectedItem属性时,在正确更新控件时一直遇到问题。

为了解决这个问题,我不得不绑定到 SelectedIndex 属性。 在我的 ViewModel 中处理"索引"属性更麻烦,但它解决了ComboBox未更新的问题。