0
votes

I am using an MVVM pattern and have a ComboBox that binds to properties in the viewmodel like this:

<ComboBox ItemsSource="{Binding Path=ItemCollection}"
          SelectedItem="{Binding Path=SelectedItem}">
</ComboBox>

This works fine. In the viewModel I have

private MyData _selectedItem;

public List<MyData> ItemCollection { get; set; }
public MyData SelectedItem
{
    get { return _selectedItem; }
    set
    {
        _selectedItem = value;
        RaisePropertyChanged();
    }
}

which also works fine. The ItemCollection binds to the ItemSource of the ComboBox and the SelectedItem gets updated when a new item is selected in the ComboBox.

I want to manually change the SelectedItem in specific cases. Like this (I skip null checks for the sake of simplicity):

public MyData SelectedItem
{
    get { return _selectedItem; }
    set
    {
        if (value.Name == "Jump to the First item")
            _selectedItem = ItemCollection.First();
        else
            _selectedItem = value;
        RaisePropertyChanged();
    }
}

This assumes that the type MyData has a string property thats called Name.

The problem is that if the conditional statement is true, the ItemSource of the ComboBox WILL get updated, however the actual visible selection of the the comboBox will not.

To give some context the comboBox actually binds to a CompositeCollection where there is one item that is styled as a button, so when clicked a dialog box is opened and the result of the dialogresult is determining what item in the comboBox should be selected.. -- Just no matter what I do the "Button" will always stay selected.

2

2 Answers

1
votes

Is your INotifyPropertyChanged interface implemented properly?

Usually you would put your property name e.g. SelectedItem in the call to the function you raise the PropertyChanged event with.

Example courtesy of MSDN below. https://msdn.microsoft.com/en-us/library/ms743695(v=vs.110).aspx

namespace SDKSample
    {
        // This class implements INotifyPropertyChanged
        // to support one-way and two-way bindings
        // (such that the UI element updates when the source
        // has been changed dynamically)
        public class Person : INotifyPropertyChanged
        {
            private string name;
            // Declare the event
            public event PropertyChangedEventHandler PropertyChanged;

            public Person()
            {
            }

            public Person(string value)
            {
                this.name = value;
            }

            public string PersonName
            {
                get { return name; }
                set
                {
                    name = value;
                    // Call OnPropertyChanged whenever the property is updated
                    OnPropertyChanged("PersonName");
                }
            }

            // Create the OnPropertyChanged method to raise the event
            protected void OnPropertyChanged(string name)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(name));
                }
            }
        }
    }
}
1
votes

The problem was that the comboBox got confused when trying to set a selected item while a it was already in the process of setting another selected item.

Solution is to set the IsAsync property to true so the SelectedItem will be set asynchronously.

<ComboBox ItemsSource="{Binding Path=ItemCollection}"
          SelectedItem="{Binding Path=SelectedItem, IsAsync=True}">
</ComboBox>

When doing this it is important to invoke code back on the mainthread:

Application.Current.Dispatcher.Invoke(() =>
    {
        /* code here */
    }
});