使用MVVM重置组合框中的组合框选定项目

fhn*_*eer 9 c# wpf combobox selecteditem mvvm

我在我的WPF应用程序中使用ComboBox并跟随MVVM.我想在ComboBox中显示一个字符串列表.

XAML:

<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem}" />
Run Code Online (Sandbox Code Playgroud)

查看型号:

public Collection<string> ItemsCollection; // Suppose this has 10 values.
private string _selectedItem;
public string SelectedItem
{
    get { return _selectedItem; }
    set
    {
        _selectedItem = value;
        Trigger Notify of property changed.
    }
}
Run Code Online (Sandbox Code Playgroud)

现在这段代码工作得很好.我可以从视图中进行选择,我可以在ViewModel中进行更改,如果我从ViewModel更改SelectedItem,我可以在我的视图中看到它.

现在这就是我想要实现的目标.当我从我的视图中更改所选项目时,我需要检查值是好/坏(或任何)设置所选项目,否则不设置它.所以我的视图模型就像这样改变了.

public string SelectedItem
{
    get { return _selectedItem; }
    set
    {
        if (SomeCondition(value))
            _selectedItem = value;           // Update selected item.
        else
            _selectedItem = _selectedItem;   // Do not update selected item.
        Trigger Notify of property changed.
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,当我执行此代码并且SomeCondition(value)返回false时,SelectedItem返回旧的字符串值,但在我的视图中,ComboBox中的选定项是我选择的值.所以我假设我的ComboBox中有10个字符串的集合.除第二和第四个元素外,所有值都很好(SomeCondition对第二个和第四个值返回false).我想要的是,如果我选择第二或第四个元素selectedItem不会改变.但是我的代码没有正确地执行此操作.如果我选择第二个元素,则视图仍然显示第二个元素为选中.我知道我的代码有问题.但它是什么?

小智 19

这是一个非常有趣的问题.首先,我同意其他人的意见,这是一种不推荐的处理无效选择的方法.正如@blindmeis所说,IDataErrorInfo是解决问题的好方法之一.

回到问题本身.满足@Faisal Hafeez想要的解决方案是:

public string SelectedItem
{
    get { return _selectedItem; }
    set
    {
        var oldItem=_selectedItem;
        _selectedItem=value;
        OnPropertyChanged("SelectedItem")

        if (!SomeCondition(value)) //If does not satisfy condition, set item back to old item
            Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => SelectedItem = oldItem),
                                                 DispatcherPriority.ApplicationIdle);
    }
}
Run Code Online (Sandbox Code Playgroud)

Dispatcher是在另一个UI同步期间处理某些UI同步的优雅方式.例如,在这种情况下,您希望在选择绑定期间重置选择.

这里的一个问题是为什么我们必须首先更新选择.这是因为SelectedItem并且SelectedValue是单独分配的,显示的内容ComboBox不依赖于SelectedItem(也许SelectedValue,我不确定).另一个有趣的观点是,如果SelectedValue发生更改,则SelectedItem必须更改但更改时SelectedItem不会更新SelectedValue.因此,您可以选择绑定,SelectedValue这样就不必先进行分配.


小智 10

我知道这有点晚了,但从 WPF 4.5 开始,您可以像这样使用 Delay 命令:

    <ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem, Mode=TwoWay, Delay=1, UpdateSourceTrigger=PropertyChanged}" />
Run Code Online (Sandbox Code Playgroud)

这让我在前几天查了几个小时的东西后救了我。对于其他可能有效也可能无效的方法,您可以阅读这篇文章及其评论。