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

时间:2013-07-25 09:51:11

标签: c# wpf mvvm combobox selecteditem

我在我的WPF应用程序中使用ComboBox并遵循MVVM。我想在ComboBox中显示一个字符串列表。

XAML:

<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem}" />

查看型号:

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.
    }
}

现在这段代码工作得很好。我可以从视图中进行选择,我可以在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.
    }
}

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

5 个答案:

答案 0 :(得分:18)

这是一个非常有趣的问题。首先,我同意其他人的意见,这是一种不推荐的处理无效选择的方法。正如@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);
    }
}

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

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

答案 1 :(得分:3)

尝试将XAML更改为此

<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

答案 2 :(得分:0)

<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedIndex="{Binding currSelection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged} " />

在您的VM中

{
    set{ 
        currSelection = -1;
    }
}

答案 3 :(得分:0)

如果您正在寻找MVVM / XAML可重用的解决方案,我将其组合在一起用于另一个线程。这使用WPF行为,并且非常易于管理。没有外部库。复制解决方案。

ComboBox Selected Item Clear Behavior

答案 4 :(得分:0)

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

    <ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem, Mode=TwoWay, Delay=1, UpdateSourceTrigger=PropertyChanged}" />

前几天经过数小时的查找,这为我节省了精力。对于可能无效的其他方法,您可以阅读this帖子及其评论。