【问题标题】:WPF ComboBox changing when it shouldn'tWPF ComboBox 在不应该更改时更改
【发布时间】:2016-11-02 15:40:14
【问题描述】:

我有一个雇主组合框。选择雇主后,表格中会填充雇主特定数据:

        <ComboBox Name="EmployerListBox"
                  IsReadOnly="True"
                  ItemsSource="{Binding EmployerCollection, UpdateSourceTrigger=PropertyChanged}"
                  SelectedItem="{Binding SelectedEmployer, UpdateSourceTrigger=PropertyChanged}" 
                  Width="150" />

这是它所绑定的属性和一个检查表是否脏的方法。如果表脏了,则提示用户如果更改 Employer,更改将丢失:

    /// <summary>
    /// Selected Employer
    /// </summary>
    public String SelectedEmployer
    {
        get
        {
            return _SelectedEmployer;
        }
        set
        {
            if (_SelectedEmployer != value && CanChangeEmployer())
            {
                _SelectedEmployer = value;
                NotifyPropertyChanged(m => m.SelectedEmployer);
                GetGarnishmentsTableView();
            }
        }
    }
    private String _SelectedEmployer = "";


    /// <summary>
    /// Method that executes each time user wants to change employers
    /// </summary>
    public Boolean CanChangeEmployer()
    {
        Boolean _returnValue = true;

        if (GarnishmentsTableIsDirty)
        {
            _returnValue = false;

            MessageBoxResult _change =
                MessageBox.Show("There are unsaved changes.  " +
                                "Changing Employers will lose any unsaved changes.  \n\n" +
                                "Are you sure you want to change Employers?", "Unsaved Changes", MessageBoxButton.YesNo);
            if (_change == MessageBoxResult.Yes)
            {
                // OK to switch employers
                _returnValue = true;
            }
        }

        return _returnValue;
    }

一切似乎都正常工作:

  • 用户选择更新表格的雇主 ('KMH')。
  • 用户对表格进行了更改。
  • 然后用户选择不同的雇主 ('MPC')
  • 提示用户更改将丢失
  • 用户选择“否”,CanChangeEmployers 返回“假”
  • SelectedEmployer 不会改变(跳过 if {} 块)

然而在 GUI 中,Employer 选项更改为用户选择的 Employer ('MPC'),即使 SelectedEmployer 没有改变。

当我窥探 ComboBox 时,我看到 ComboBox SelectedItem 已正确设置为原始 Employer ('KMH'),但 SelectedValue 和 SelectionBoxItem 都设置为新 Employer ('MPC')。

然后我尝试将 ComboBox->SelectedValue 绑定到 SelectedEmployer:

        <ComboBox Name="EmployerListBox"
                  IsReadOnly="True"
                  ItemsSource="{Binding EmployerCollection, UpdateSourceTrigger=PropertyChanged}"
                  SelectedValue="{Binding SelectedEmployer, UpdateSourceTrigger=PropertyChanged}" 
                  Width="150" />

GUI 是相同的,显示的公司不正确。但这次 Snoop 显示 ComboBox->SelectedValue 正确设置为原始 Employer ('KMH'),但 SelectedItem 和 SelectionBoxItem 都设置为新 Employer ('MPC')。

如何正确绑定 SelectedEmployer 以使 GUI 与所选雇主匹配?

【问题讨论】:

  • 在 CanChangeEmployer() 返回 false 的情况下尝试调用 NotifyPropertyChanged(...),否则绑定子系统可能会假设 SelectedEmployer 属性实际上已设置为指定的值,而实际上它具有没有更新。

标签: c# wpf combobox selectionchanged


【解决方案1】:

发生的事情是 ComboBox 改变了它的选择,Binding 更新了你的 viewmodel,然后 viewmodel 选择不改变它的私有字段。但是 ComboBox 应该如何知道更改被拒绝了?你没有说出来。

您可能认为SelectedEmployer.set 在决定保留旧值后可以简单地为SelectedEmployer 提高PropertyChanged,但我无法让它发挥作用。

执行此操作的“正确”方法是验证:让您的视图模型实现 IDataErrorInfoHere's a tutorialhere's another article。通过验证,您的IDataErrorInfo.this[propName].get 方法在ComboBox 接受新选择之前被调用,并且可以选择拒绝新选择。这就是你要找的。如果您不想要红色轮廓错误 UI 的东西,您可以使用模板来摆脱它。

尝试处理 SelectionChanged 很诱人,但事件 args 没有 Cancel,因此您无法将 SelectedItem 设置回原来的状态,这会再次引发 SelectionChanged,所以你需要一些逻辑来阻止它无限递归。修复该问题后,由于初始选择在您将其设置回之前的值之前完成,因此仍然存在可见的“闪烁”。就我个人而言,我更喜欢实现IDataErrorInfo 的轻度苦差事,而不是试图超越框架。

更新

Here's a kinda-kludgey variant of my first idea that actually works。但是,它有相同的闪烁问题。远非理想,但它比验证工作少得多。 DispatcherPriority.ApplicationIdle 是它工作的原因:它等待实际执行 lambda,直到所有来自 ComboBox 的选择更改事件内容尘埃落定。 DispatcherPriority.Background 也适合我。

【讨论】:

    猜你喜欢
    • 2016-05-13
    • 2011-12-05
    • 1970-01-01
    • 2010-10-12
    • 2019-09-11
    • 2013-03-03
    • 1970-01-01
    • 2020-01-15
    • 2013-07-01
    相关资源
    最近更新 更多