2

I am trying to bind my ComboBox to list of strings and I would like it to show default value once Window is loaded.

To do that, I created a ViewModel class like:

namespace MyData
{
    class ViewModel
    {
        public ViewModel()
        {
            this.Name = "";
            this.Age = 0;
            this.Address = "";
            this.DateOfPurchase = DateTime.Now.AddDays(-30);
            this.CarModel = "VW"; //I want to set VW as default but options are Mazda, VW, Audi
        }

        public IEnumerable<String> CarModels
        {
            get
            {
                var carModels = new String[] {"Mazda", "VW", "Audi"};
                //CarModel = cars.FirstOrDefault(car => CarModel == "VW");  //this is not needed

                return carModels;
            }
        }

        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
        public DateTime DateOfPurchase { get; set; }
        public String CarModel { get; set; }
    }
}

Then I set DataSource of Window to my ViewModel

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    this.DataContext = new ViewModel();
}

Finally, I would like to bind my controls to this data. I have done so for all others except my ComboBox. I would like it to get the string array with models (Mazda, VW, and Audi) as its ComboBoxItems and to default to 2nd which is VW once form loads.

Then I bind it like this in my XAML:

<ComboBox Name="cbCarModels" SelectedItem="{Binding CarModel, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding CarModels}">

And this works!

5
  • Just an fyi, the way you set Car = works if it's a string, but as soon as the items are not strings it won't work. The selected item must be an instance from the items source. The commented out // this is not needed is actually the better all around approach. Commented Dec 17, 2015 at 4:01
  • The item will be string. It should not be called Car but rather CarModel. I'll update Commented Dec 17, 2015 at 4:05
  • @jeff But would you mind explaining. Why can't I use strings. I understand that if I wanted my dropdown to hold Objects like Cars, In that case, I would probably have to override toString or my Car class to show what I want. Commented Dec 17, 2015 at 4:07
  • You CAN use strings. That is not an issue. As you move forward into your app, you will find that is more common to bind to a objects not strings. Following your example, say Car was not a string but an object with more properties. You'd then be binding to Car.Name Commented Dec 17, 2015 at 17:50
  • fwiw...if your overriding ToString, your doing it wrong, your just not getting the wpf paradigm yet. Commented Dec 17, 2015 at 18:17

3 Answers 3

2

Off the top of my head

In xaml

<Combobox ItemsSource="{Binding Path=CarModels}", SelectedItem="{Binding SelectedCar}/>

You'll need to create ViewModel.SelectedCar model. Set it in vm.ctor

this.SelectedCar = Cars[1]

You might have to add Path=CarModels, Mode=TwoWay to binding.

Sign up to request clarification or add additional context in comments.

1 Comment

I figured it out already but thanks Jeff. I updated my question. It is the answer now.
1

In addition, it's sometimes more convenient to be able to bind to complex objects (e.g. while editing the properties of existing objects). In order for that you can, as you suggested, overwrite the ToString() method of this object, but you could also bind the displayed value in the combobox item to a secific member of that object within the XAML via DisplayMemberPath property:

<ComboBox ItemsSource="{Binding CarModel}" DisplayMemberPath="Name" SelectedItem="{Binding CarModels}" />

The advantage is that you keep this additional ToString() code out of your POCOs.

Comments

0

If you are going to take advantage of MVVM with WPF (or any XAML-based language), then understand that the DataBinding Engine works heavily with the INotifyPropertyChanged interface. The user interface subscribes to PropertyChanged events, and updates the UI controls based on the binding.

Here is an example, with only the relevante portions. Note that I don't include the implementation of INPC, but there are many frameworks that provide an abstract base class, and if you don't want to go that route there are many resources out there that describe how to implement the INPC interface.

MyViewModel.cs:

public class MyViewModel : INotifyPropertyChanged
{
    public MyViewModel()
    {
        CarModels = new[] {"Mazda", "VW", "Audi"};
        SelectedCarModel = "VW";
    }

    public IEnumerable<string> CarModels { get; private set; }

    private string _selectedCarModel;
    public string SelectCarModel
    {
        get { return _selectedCarModel; }
        set
        {
            if (_selectedCarModel == value) return;

            _selectedCarModel = value;
            OnPropertyChanged("SelectedCarModel");
        }
    }
}

XAML:

<ComboBox ItemsSource="{Binding Path=CarModels, Mode=OneTime}"
          SelectedItem="{Binding Path=SelectedCarModel}" />

Simply put, if you implement the INPC and you raise a property change notification, the DataBinding engine will call the property get methods based on the name of the property. It will then update the necessary UI control. Additionally, the user interface will update the viewmodel as well.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.