Ashwin
Ashwin

Reputation: 131

ObservableCollection or List data bind with comboBox using MVVM?

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

Answers (7)

Ashwin
Ashwin

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

Rachel
Rachel

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

ken2k
ken2k

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

crypted
crypted

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

Dmitriy
Dmitriy

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

Tom Brothers
Tom Brothers

Reputation: 6017

You need to bind to a public property. In your example, combodata is private.

Upvotes: 0

EgorBo
EgorBo

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

Related Questions