Binding Combobox Selecteditem Using Mvvm

Binding ComboBox SelectedItem using MVVM

You seem to be unnecessarily setting properties on your ComboBox. You can remove the DisplayMemberPath and SelectedValuePath properties which have different uses. It might be an idea for you to take a look at the Difference between SelectedItem, SelectedValue and SelectedValuePath post here for an explanation of these properties. Try this:

<ComboBox Name="cbxSalesPeriods"
ItemsSource="{Binding SalesPeriods}"
SelectedItem="{Binding SelectedSalesPeriod}"
IsSynchronizedWithCurrentItem="True"/>

Furthermore, it is pointless using your displayPeriod property, as the WPF Framework would call the ToString method automatically for objects that it needs to display that don't have a DataTemplate set up for them explicitly.


UPDATE >>>

As I can't see all of your code, I cannot tell you what you are doing wrong. Instead, all I can do is to provide you with a complete working example of how to achieve what you want. I've removed the pointless displayPeriod property and also your SalesPeriodVO property from your class as I know nothing about it... maybe that is the cause of your problem??. Try this:

public class SalesPeriodV
{
private int month, year;

public int Year
{
get { return year; }
set
{
if (year != value)
{
year = value;
NotifyPropertyChanged("Year");
}
}
}

public int Month
{
get { return month; }
set
{
if (month != value)
{
month = value;
NotifyPropertyChanged("Month");
}
}
}

public override string ToString()
{
return String.Format("{0:D2}.{1}", Month, Year);
}

public virtual event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged(params string[] propertyNames)
{
if (PropertyChanged != null)
{
foreach (string propertyName in propertyNames) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
PropertyChanged(this, new PropertyChangedEventArgs("HasError"));
}
}
}

Then I added two properties into the view model:

private ObservableCollection<SalesPeriodV> salesPeriods = new ObservableCollection<SalesPeriodV>();
public ObservableCollection<SalesPeriodV> SalesPeriods
{
get { return salesPeriods; }
set { salesPeriods = value; NotifyPropertyChanged("SalesPeriods"); }
}
private SalesPeriodV selectedItem = new SalesPeriodV();
public SalesPeriodV SelectedItem
{
get { return selectedItem; }
set { selectedItem = value; NotifyPropertyChanged("SelectedItem"); }
}

Then initialised the collection with your values:

SalesPeriods.Add(new SalesPeriodV() { Month = 3, Year = 2013 } );
SalesPeriods.Add(new SalesPeriodV() { Month = 4, Year = 2013 } );

And then data bound only these two properties to a ComboBox:

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

That's it... that's all you need for a perfectly working example. You should see that the display of the items comes from the ToString method without your displayPeriod property. Hopefully, you can work out your mistakes from this code example.

Getting SelectedItem of ComboBox (MVVM)

The red box is an indication of a validation error from your Binding ,
The most common error would be that the BindingSource and the BindingTarget are not of the same type.

Use SelectedValue and SelectedValuePath to bind to your Room object.

CS :

public class Room
{
public string RoomName { get; set; }
}

public class RoomWrapper
{
public Room Room { get; set; }
}

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}

public List<RoomWrapper> RoomWrappers
{
get
{
var list = new List<RoomWrapper>();
for (int i = 0; i < 10; i++)
{
list.Add(new RoomWrapper { Room = new Room { RoomName = "Room " + i } });
}

return list;
}
}

private Room selectedRoom;
public Room SelectedRoom
{
get { return selectedRoom; }
set
{
selectedRoom = value;
}
}

XAML :

    <ComboBox ItemsSource="{Binding RoomWrappers}" 
DisplayMemberPath="Room.RoomName"
SelectedValuePath="Room"
SelectedValue="{Binding SelectedRoom, Mode=TwoWay}" />

C# WPF MVVM ComboBox SelectedItem

You need do Sync the list with the current selected item:

1.Xaml:

<ComboBox ItemsSource="{Binding Contacts}" SelectedItem="{Binding SelectedContact}" IsSynchronizedWithCurrentItem="True" />

2.ViewModel:

public ObservableCollection<ContactModel> Contacts { get; set; }

public MainViewModel()
{
_model = new Model {Name = "Prop Name" };
Contacts = new ObservableCollection<ContactModel>
{
new ContactModel {Id = 1, Name = "John Doe", Phone = "+166666333"},
new ContactModel {Id = 2, Name = "Some Guy", Phone = "+123456789"}
};
SelectedContact = Contacts[0];
}

private ContactModel _SelectedContact;

public ContactModel SelectedContact
{
get { return _SelectedContact; }
set
{
_SelectedContact = value;
OnPropertyChanged(nameof(SelectedContact));
}
}

Binding two objects with Combo Box SelectedItem WPF MVVM (ItemsControl)

If anyone else get stuck on similar problem like this where you want selected statements to match selection from multiple combo boxes and you're wondering how to identity which combo box was used. I've overcame this by having a list of models for each combo box. This way you can store ID of the statement, it also allows to easier store selected items should you ever want to load selection from the database instead of only storing it.

  public class QuestionMatchesModel :BaseModel
{
public ObservableCollection<MatchOptions> Answers { get; set; }

private MatchOptions _selected;

public MatchOptions Selected
{
get => _selected;
set
{
_selected = value;
RaisePropertyChanged("Selection");
}
}
}

public class MatchOptions : BaseModel
{
public long ResponseId { get; set; }
public long MatchId { get; set; }
public string Answer { get; set; }
}

}

Example Model that can be used, create a list out of this for each statement in your main model.

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

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>

WPF MVVM Combobox SelectedItem not working properly

As mentioned by @Clemens I had two view model instances at the same time.
One created in the UserControl's constructor (code behind) and other on the XAML Resources.

So, I removed the last one and everything works fine.

<!--
<UserControl.Resources>
<viewmodels:LiveGraphViewModel x:Key="LIVviewModel"/>
</UserControl.Resources>
-->

<Label Content="Porta COM: "></Label>
<ComboBox ItemsSource="{Binding Available_COMPorts}"
SelectedValue="{Binding SelectedCOMPort, Mode=TwoWay}" />
<Button Content="Connect/Disconnect"
Command="{Binding Path=ConnectButtonCommand}" />

WPF - MVVM - ComboBox SelectedItem

The category you are setting in this line -

NodeCategory = some_list_of_other_objects.Category;

and one present in your Categories collection(ItemsSource="{Binding Categories}") should be referring to same object. If they are not then SelectedItem won't work.

Solution 1 -

You can also try to use SelectedValuePath like this -

<ComboBox x:Name="categoryComboBox" 
ItemsSource="{Binding Categories}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding NodeCategory, Mode=TwoWay}" />

and in code you can do something like this -

private string _NodeCategory;
public string NodeCategory
{
get
{
return _NodeCategory;
}
set
{
_NodeCategory = value;
OnPropertyChanged("NodeCategory");
}
}

and set selected item like this -

NodeCategory = some_list_of_other_objects.Category.Name;

and use selected value like this -

Category selectedCategory = 
some_list_of_other_objects.FirstOrDefault(cat=> cat.Name == NodeCategory);

or

Category selectedCategory = 
Categories.FirstOrDefault(cat=> cat.Name == NodeCategory);

Solution 2 -

Another possible solution can be -

NodeCategory = 
Categories.FirstOrDefault(cat=> cat.Name == some_list_of_other_objects.Category.Name);

this way your NodeCategory property will have the reference of an object in Categories collection and SelectedItem will work.



Related Topics



Leave a reply



Submit