简体   繁体   English

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

[英]Reset combobox selected item on set using MVVM

I am using a ComboBox in my WPF application and following MVVM.我在 WPF 应用程序中使用 ComboBox 并遵循 MVVM。 There is a list of strings which I want to show in my ComboBox.我想在 ComboBox 中显示一个字符串列表。

XAML: XAML:

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

View Model:查看型号:

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

Now this code is working absolutely fine.现在这段代码工作得很好。 I am able to select from view and I can get changes in ViewModel and if I change SelectedItem from my ViewModel I can see it in my view.我可以从视图中进行选择,并且可以在 ViewModel 中进行更改,如果我从 ViewModel 中更改 SelectedItem,则可以在我的视图中看到它。

Now here is what I am trying to achieve.现在这就是我想要实现的目标。 When I change selected item from my view I need to put a check that value is good/bad (or anything) set selected item else do not set it.当我从我的视图中更改所选项目时,我需要检查值是好/坏(或任何)设置所选项目,否则不要设置它。 So my view model changes like to this.所以我的视图模型变成了这样。

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

Now when I execute this code and SomeCondition(value) returns false, SelectedItem returns old string value, but in my view selected item in ComboBox is the the value which I selected.现在,当我执行此代码并且 SomeCondition(value) 返回 false 时,SelectedItem 返回旧字符串值,但在我看来,ComboBox 中的选定项是我选择的值。 So lets assume I have collection of 10 strings showing in my ComboBox.所以让我们假设我的 ComboBox 中显示了 10 个字符串的集合。 All values are good except second and fourth element (SomeCondition returns false for 2nd and 4th value).除了第二个和第四个元素外,所有值都很好(SomeCondition 为第二个和第四个值返回 false)。 What I want that if I select 2nd or 4th element selectedItem do not change.如果我选择第 2 个或第 4 个元素 selectedItem,我想要什么不要改变。 But my code is not doing this properly.但是我的代码没有正确执行此操作。 If I select 2nd element then view still displays 2nd element as selected.如果我选择第二个元素,则视图仍将第二个元素显示为选定的。 I know there is something wrong in my code.我知道我的代码有问题。 But what is it?但它是什么?

This is a very interesting question.这是一个非常有趣的问题。 First I agree with other guys that this is a not recommended approach to handle invalid selection.首先,我同意其他人的看法,这是处理无效选择的不推荐方法。 As @blindmeis suggests, IDataErrorInfo is one of good way to solve it.正如@blindmeis 所建议的那样, IDataErrorInfo是解决它的好方法之一。

Back to the question itself.回到问题本身。 A solution satisfying what @Faisal Hafeez wants is:满足@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 is an elegant way to handle some UI synchronization during another UI sync. Dispatcher是一种在另一个 UI 同步期间处理某些 UI 同步的优雅方式。 For example in this case, you want to reset selection during a selection binding.例如,在这种情况下,您希望在选择绑定期间重置选择。

A question here is why we have to update selection anyway at first.这里的一个问题是为什么我们首先必须更新选择。 That's because SelectedItem and SelectedValue are separately assigned and what display on ComboBox does not depend on SelectedItem (maybe SelectedValue , I am not sure here).那是因为SelectedItemSelectedValue是单独分配的,并且ComboBox上显示的内容不依赖于SelectedItem (可能SelectedValue ,我在这里不确定)。 And another interesting point is if SelectedValue changes, SelectedItem must change but SelectedItem does not update SelectedValue when it changes.而另一个有趣的一点是,如果改变的SelectedValue, SelectedItem必须改变,但SelectedItem不更新SelectedValue ,当它改变。 Therefore, you can choose to bind to SelectedValue so that you do not have to assign first.因此,您可以选择绑定到SelectedValue以便您不必先分配。

I know this is a bit late but as of WPF 4.5 you can use the Delay command like so:我知道这有点晚了,但从 WPF 4.5 开始,您可以像这样使用 Delay 命令:

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

This saved me after hours of looking up stuff the other day.这让我在前几天查了几个小时的东西后救了我。 For other methods which may or may not work you can read this post and its comments.对于其他可能有效也可能无效的方法,您可以阅读这篇文章及其评论。

尝试将 XAML 更改为此

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

And in your VM在你的虚拟机中

{
    set{ 
        currSelection = -1;
    }
}

If you are looking for a MVVM / XAML re-usable solution, I put this together for another thread.如果您正在寻找 MVVM/XAML 可重用的解决方案,我将其放在另一个线程中。 This uses a WPF Behavior and is very simple to manage.这使用 WPF 行为并且非常易于管理。 No external libs.没有外部库。 Copy in solution.在解决方案中复制。

ComboBox Selected Item Clear Behavior ComboBox 选定项清除行为

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM