Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
408 views
in Technique[技术] by (71.8m points)

c# - Reset combobox selected item on set using MVVM

I am using a ComboBox in my WPF application and following MVVM. There is a list of strings which I want to show in my ComboBox.

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.

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. So lets assume I have collection of 10 strings showing in my ComboBox. All values are good except second and fourth element (SomeCondition returns false for 2nd and 4th value). What I want that if I select 2nd or 4th element selectedItem do not change. 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

Back to the question itself. A solution satisfying what @Faisal Hafeez wants is:

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. 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). And another interesting point is if SelectedValue changes, SelectedItem must change but SelectedItem does not update SelectedValue when it changes. Therefore, you can choose to bind to SelectedValue so that you do not have to assign first.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...