views:

142

answers:

2

I have a combo box that I have bound to a list that exists in my viewmodel. Now when a users makes a selection in that combo box I want a second combo box to update its content.

So, for example, combobox1 is States and combobox2 should contain only the Zipcodes of that state.

But in my case I don't have a predefined lists before hand for combobox2, I need to go fetch from a db.

Also, if needed, I could get all the potential values for combobox2 (for each combobox1 value) before hand, but I'd like to avoiding that if I can.

How do I implement in WPF and using MVVM? I'm fairly new to this whole wpf\databinding\mvvm world.

+2  A: 

Something like the following. Note that the code is drastically simplified for the sake of example. In reality, your ViewModel would implement INotifyPropertyChanged and raise PropertyChanged events when the properties were modified.

The key though is the setter of SelectedState. Your ComboBox would bind its SelectedValue property to the ViewModel's SelectedState property. When the property changed, the ZipCodes collection gets re-loaded which another combobox would be bound to.

class MyViewModel {

    public ObservableCollection<string> States {
        get;
        private set;
    }

    public ObservableCollection<string> ZipCodes {
        get;
        private set;
    }

    public string SelectedState {
        get { return _selectedState; }
        set {
            _selectedState = value;
            LoadZipCodes(_selectedState);
        }
    }

    public string SelectedZipCode {
        get;
        set;
    }

    void LoadZipCodes(string state) {
        // repopulate the ZipCodes property
    }

}
Josh Einstein
Just a couple maybe obvious tips to add...1. Clear the Collection before adding the new Zips2. I would definitely attempt to implement an asynchronous pattern, you wouldn't want the screen to freeze, until the call comes back.3. If implementing an async approach you may want to disable the Zip combo, until the call comes back.
Agies
A: 

Another solution. The approximate model:

class StateViewModel
{
    public string StateName
    {
        get {...}
        set {...}
    }

    public ObservableCollection<ZipCodeViewModel> ZipCodes
    {
        get {...}
        set {...}
    }
}

class ZipCodeViewModel
{
    public string ZipCodeName
    {
        get {...}
        set {...}
    }
}

class MainViewModel
{
    public ObservableCollection<StateViewModel> States
    {
        get {...}
        set {...}
    }
}

And XAML:

<ComboBox ItemsSource="{Binding Path=States}" IsSynchronizedWithCurrentItem="True">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <Label Content="{Binding Path=StateName}"></Label>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

<ContentControl Content="{Binding Path=States}">
    <ContentControl.ContentTemplate>
        <DataTemplate>
            <ComboBox ItemsSource="{Binding Path=ZipCodes}">
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <Label Content="{Binding Path=ZipCodeName}"></Label>
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>
        </DataTemplate>
    </ContentControl.ContentTemplate>
</ContentControl>
darja