c# - WPF ComboBox 在不应该更改的时候更改

标签 c# wpf combobox selectionchanged

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

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

这是它绑定(bind)的属性和一个检查表是否脏的方法。如果表是脏的,则提示用户如果更改 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')
  • 提示用户更改将丢失
  • 用户选择“No”,CanChangeEmployers 返回“false”
  • SelectedEmployer 不改变(跳过 if {} block )

但在 GUI 中,雇主选项更改为用户选择的雇主(“MPC”),即使 SelectedEmployer 没有更改。

当我窥探 ComboBox 时,我发现 ComboBox SelectedItem 已正确设置为原始雇主(“KMH”),但 SelectedValue 和 SelectionBoxItem 都设置为新雇主(“MPC”)。

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

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

而且 GUI 是一样的,显示的是不正确的公司。但这次 Snoop 显示 ComboBox->SelectedValue 已正确设置为原始雇主('KMH'),但 SelectedItem 和 SelectionBoxItem 都设置为新雇主('MPC')。

如何正确绑定(bind) SelectedEmployer 以便 GUI 与选定的雇主相匹配?

最佳答案

发生的事情是 ComboBox 更改其选择,Binding 更新您的 View 模型,然后 View 模型选择不更改其私有(private)字段。但是 ComboBox 怎么知道更改被拒绝了呢?你没有告诉它。

您可能认为 SelectedEmployer.set 可以在决定保留旧值后简单地为 SelectedEmployer 提高 PropertyChanged,但我无法理解那个工作。

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

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

更新

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

关于c# - WPF ComboBox 在不应该更改的时候更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38124864/

相关文章:

c# - 为 Twitter 情绪分析项目寻找 C# 中的开源朴素贝叶斯分类器

c# - 任务/线程中的 CredentialsCache.DefaultCredentials

c# - 声明一个具有增量值的数组 - 有捷径吗?

c# - TreeView 上下文菜单在 HierarchicalDataTemplate 中不起作用

javascript - 重置自动完成组合框

c# - 关于mvvm页面导航的两个问题

c# - 如何在.Net core中使用Google Sheets API?

C#:如何调整一个窗口窗体只允许按宽度而不是按高度调整大小?

javascript - C# WPF WebBrowser - 如何将数组传递给 javascript 函数

c# - WPF 自定义组合框在项目上显示 "System.Windows.Styles"