Search code examples
c#wpfmvvmobservablecollectionprism-6

Setting and Showing the SelectedItem in ComboBox from VM in WPF Prism MVVM


I am trying to set a ComboBox SelectedItem from my VM. I think I am close, but I do not know how to show the SelectedItem in the ComboBox when it is set from the VM.

The textbox is has a binding to the SelectedItem Property. When I run it, it will indeed show Friday in my TextBox, but the combobox is still empty. The TextBox also shows any value I may select in my ComboBox, So I think Ihave done that part ok. What do I need to change to also show it in the ComboBox? Not sure I made a mistake in the code, or I simply need to do something I am not aware of to be honest.

The sample DB is WeekDays

WeekDayID    WeekDayShort   WeekDayLong
    1            Sun          Sunday
    2            Mon          Monday
    3            Tue          Tuesday
    4            Wed          Wednesday
    5            Thu          Thursday
    6            Fri          Friday
    7            Sat          Saturday

Model WeekDays.cs :

public partial class WeekDays
{
    public int WeekDayID { get; set; }
    public string WeekDayShort { get; set; }
    public string WeekDayLong { get; set; }
}

ViewModel MainViewModel.cs :

class MainViewModel : BindableBase
{
    private ObservableCollection<WeekDays> _weekDays;
    public ObservableCollection<WeekDays> WeekDays
    {
        get
        {
            return _weekDays;
        }
        set
        {
            SetProperty(ref _weekDays, value);
        }
    }

    private WeekDays _selectedWeekDay;
    public WeekDays SelectedWeekDay
    {
        get
        {
            return _selectedWeekDay;
        }
        set
        {
            SetProperty(ref _selectedWeekDay, value);
        }
    }

    private void FillWeekDays()
    {
        using (NLTrader01Entities nlt = new NLTrader01Entities())
        {
            var q = (from a in nlt.WeekDays select a).ToList();
            WeekDays = new ObservableCollection<WeekDays>(q);
        }
    }

    public MainViewModel()
    {
        FillWeekDays();
        Initialize();
    }

    public void Initialize()
    {
        using (NLTrader01Entities nlt = new NLTrader01Entities())
        {
            SelectedWeekDay = (from a in nlt.WeekDays where a.WeekDayLong == "Friday" select a).Single();
        }
    }
}

And the View.xaml :

<ComboBox
    ItemsSource="{Binding WeekDays}"
    DisplayMemberPath="WeekDayLong"
    SelectedItem="{Binding SelectedWeekDay, Mode=TwoWay}">
</ComboBox>
<TextBox
    Text="{Binding SelectedWeekDay.WeekDayLong, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</TextBox>

Solution

  • Thanks to Clemens for guiding me in the right direction here 2 possible answers that worked for me.

    Solution 01:

    Continuation of using SelectedItem and introducing SelectedIndex.

    ViewModel MainViewModel.cs :

    class MainViewModel : BindableBase
    {
        private ObservableCollection<WeekDays> _weekDays;
        public ObservableCollection<WeekDays> WeekDays
        {
            get
            {
                return _weekDays;
            }
            set
            {
                SetProperty(ref _weekDays, value);
            }
        }
    
        private int _selectedIndex;
        public int SelectedIndex
        {
            get
            {
                return _selectedIndex;
            }
            set
            {
                SetProperty(ref _selectedIndex, value);
            }
        }
    
        private WeekDays _selectedWeekDay;
        public WeekDays SelectedWeekDay
        {
            get
            {
                return _selectedWeekDay;
            }
            set
            {
                SetProperty(ref _selectedWeekDay, value);
            }
        }
    
        private void FillWeekDays()
        {
            using (NLTrader01Entities nlt = new NLTrader01Entities())
            {
                var q = (from a in nlt.WeekDays select a).ToList();
                WeekDays = new ObservableCollection<WeekDays>(q);
            }
        }
    
        public MainViewModel()
        {
            FillWeekDays();
            SelectedIndex = 4;        
        }
    }
    

    And the View.xaml :

    <ComboBox
        ItemsSource="{Binding WeekDays}"
        DisplayMemberPath="WeekDayLong"
        SelectedItem="{Binding SelectedWeekDay}"
        SelectedIndex="{Binding SelectedIndex}">
    </ComboBox>
    <TextBox
        Text="{Binding SelectedWeekDay.WeekDayLong}">
    </TextBox>
    

    Solution 02:

    Combination of using SelectedIndex and SelectedValue with SelectedValuePath.

    ViewModel MainViewModel.cs :

    class MainViewModel : BindableBase
    {
        private ObservableCollection<WeekDays> _weekDays;
        public ObservableCollection<WeekDays> WeekDays
        {
            get
            {
                return _weekDays;
            }
            set
            {
                SetProperty(ref _weekDays, value);
            }
        }
    
        private int _selectedIndex;
        public int SelectedIndex
        {
            get
            {
                return _selectedIndex;
            }
            set
            {
                SetProperty(ref _selectedIndex, value);
            }
        }
    
        private WeekDays _selectedWeekDay;
        public WeekDays SelectedWeekDay
        {
            get
            {
                return _selectedWeekDay;
            }
            set
            {
                SetProperty(ref _selectedWeekDay, value);
            }
        }
    
        private void FillWeekDays()
        {
            using (NLTrader01Entities nlt = new NLTrader01Entities())
            {
                var q = (from a in nlt.WeekDays select a).ToList();
                WeekDays = new ObservableCollection<WeekDays>(q);
            }
        }
    
        public MainViewModel()
        {
            FillWeekDays();
            SelectedIndex = 4;       
        }
    }
    

    And the View.xaml :

    <ComboBox
        ItemsSource="{Binding WeekDays}"
        DisplayMemberPath="WeekDayLong"
        SelectedValuePath="WeekDayLong"
        SelectedValue="{Binding SelectedWeekDay}"
        SelectedIndex="{Binding SelectedIndex}">
    </ComboBox>
    <TextBox
        Text="{Binding SelectedWeekDay.WeekDayLong}">
    </TextBox>