Reputation: 131
I have ObservableCollection items i want to bind this data to my comboBox. How to bind data with comboBox? I am using MVVM pattern so suggest me how to bind data using MVVM pattern
I am trying to do this code but not working properly.. In my XAML PAGE:
<ComboBox x:Name="comobo1"
DisplayMemberPath="CardTypeName"
SelectedValuePath="CardTypeID"
ItemsSource="{Binding Path=combodata}">
</ComboBox>
In my ViewModel
(Card
is my model)
public ObservableCollection<Card> combodata = new ObservableCollection<Card>();
foreach (var item in App.db.States)
{
Card c = new Card(item.StateName, item.StateID);
combodata.Add(c);
}
How to bind this combodata to my comboBox - what am I doing wrong ?
Upvotes: 0
Views: 15243
Reputation: 131
Correct Answer is :
In XAML PAGE":
<CollectionViewSource x:Key="comboBoxCollection" Source="{Binding comboData}"></CollectionViewSource>
<DataTemplate x:Key="ComboBoxDataTemplate">
<Grid MinHeight="25">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ComboBox x:Name="comobo1" DisplayMemberPath="CardTypeName" SelectedValuePath="CardTypeID" ItemsSource="{Binding Source={StaticResource comboBoxCollection }}">
</ComboBox>
</Grid>
</DataTemplate>
In ViewModel:
private ObservableCollection<Card> _combodata;
public ObservableCollection<Card> comboData
{
get
{
if (_combodata == null)
_combodata = new ObservableCollection<Card>();
return _combodata;
}
set
{
if (value != _combodata)
_combodata = value;
}
}
if (_objCardField.FieldTag == "State")
{
cards = new Cards();
foreach (var item in App.db.States)
{
Card c = new Card(item.StateName, item.StateID);
comboData.Add(c);
}
}
Upvotes: 0
Reputation: 132648
My best guess is your ComboBox's DataContext
is not set to an instance of your ViewModel
I often use Snoop to debug DataContext problems with the application. It allows you to view your Visual Tree, and see what the DataContext is for all controls.
The DataContext is the data your UI is bound to. Usually the DataContext is set higher up in the Visual Tree, such as on the Window object, although as an example the following line of code would set the ComboBox's DataContext to a new instance of your ViewModel, and then your ComboBox should be able to find the combodata
collection to bind to it.
comobo1.DataContext = new MyViewModel();
Also, change your combodata
from a Field
(no get/set accessor methods) to a Property
(see Dmitriy's Answer for an example)
Upvotes: 1
Reputation: 49013
You have to bind to a public property of the view model that should implement INotifyPropertyChanged
.
Here's what you should do:
View:
<ComboBox x:Name="comobo1" DisplayMemberPath="CardTypeName" SelectedValuePath="CardTypeID" ItemsSource="{Binding Path=ComboData}" />
ViewModel:
public class MyViewModel : INotifyPropertyChanged
{
private ObservableCollection<Card> comboData;
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Card> ComboData
{
get
{
return this.comboData;
}
set
{
if (this.comboData != value)
{
this.comboData = value;
this.NotifyPropertyChanged("ComboData");
}
}
}
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
EDIT: you'll also need to set the DataContext
property of your view. The simple way is to affect the instance of your ViewModel to the DataContext
property in the code-behind of your view.
Upvotes: 3
Reputation: 10306
There are following problems with the code.
1.You can not bind to private field or property. It should be public property.
2.You only provided ItemsSource="{Binding Path=combodata}"
but did not provide a source. Where does combodata come from ?
ObservableCollection has nothing to do unless your combo box items doe not change once filled. In this case List can work well.
To make it work, Change your combodata to public property as
public ObservableCollection<Card> combodata {get;set;}
then,
<ComboBox x:Name="comobo1"
DisplayMemberPath="CardTypeName"
SelectedValuePath="CardTypeID"
ItemsSource="{Binding Path=combodata}" ElementName=mainWindow>
</ComboBox>
by specifying ElementName you are telling WPF binding engine to look for the combodata property of the mainWindow class.
I hope this helps.
Upvotes: 2
Reputation: 664
private ObservableCollection<Card> _combodata;
Public ObservableCollection<Card> comboData
{
get
{
if (_combodata == null)
_combodata = new ObservableCollection<Card>();
return _combodata;
}
set
{
if (value != _combodata)
_combodata = value;
}
}
<ComboBox x:Name="comobo1"
DisplayMemberPath="CardTypeName"
SelectedValuePath="CardTypeID"
ItemsSource="{Binding Path=comboData}">
</ComboBox>
And don't forget to set a DataContext property.
Upvotes: 2
Reputation: 6017
You need to bind to a public property. In your example, combodata is private.
Upvotes: 0
Reputation: 6142
At first: your combodata
has private access modifier instead of public. At second: combodata
must be property but not the field. And you'd better add INotifyPropertyChanged implementation to you class.
Upvotes: 3