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
Ensure That Httpconfiguration.Ensureinitialized()
Why Value-Types Are Stored Onto Stacks
How to Get Next (Or Previous) Enum Value in C#
How to Create Xmlelement Attributes with Prefix
ASP.NET Core Identity - Get Current User
Why Is a Round-Trip Conversion via a String Not Safe for a Double
How to Use Linq Distinct() with Multiple Fields
How to Access Session in a Webmethod
What Makes a Method Thread-Safe? What Are the Rules
The Source Was Not Found, But Some or All Event Logs Could Not Be Searched
How to Create a File and Any Folders, If the Folders Don't Exist
Associate a Private Key with the X509Certificate2 Class in .Net
.Net Configuration (App.Config/Web.Config/Settings.Settings)
Set Content-Type of Media Files Stored on Blob
Difference Between Select and Convertall in C#
How to Change Route to Username After Logged In
Setting Up Swagger (ASP.NET Core) Using the Authorization Headers (Bearer)