user2734327
user2734327

Reputation: 43

How to refresh combobox after changing selection in another combobox in WPF

I have to combobox in my window:

<ComboBox x:Name="cbDeps"
        ItemsSource="{Binding}" DisplayMemberPath="sName" SelectedValuePath="nDepartmentIdn"
        Grid.Row="0" Margin="0,52,215,0" Grid.Column="1" SelectionChanged="cbUsers_SelectionChanged"/>
<ComboBox x:Name="cbUsersDep"
        ItemsSource="{Binding}" DisplayMemberPath="sUserName" SelectedValuePath="nUserIdn"
        Grid.Row="0" Margin="218,52,0,0" Grid.Column="1"/>

and I want when I select a value in the first combobox, the second be filled only by items of the selected item. I get these items using this method:

public ObservableCollection<DataModel.TB_USER> listUsersParDeps(int numDep)
{
    var userDeps = (from DataModel.TB_USER ud in SessionContext.DBContext.TB_USER
                    where ud.nDepartmentIdn==numDep
                    select ud);

    foreach (var userDep in userDeps)
    {
        userM.ListUserDep.Add(userDep);
    }

    return userM.ListUserDep;
}

and I put them in the datacontext:

cbUsersDep.DataContext = userVM.listUsersParDeps(int.Parse(cbDeps.SelectedValue.ToString()));

Upvotes: 0

Views: 3223

Answers (1)

poke
poke

Reputation: 387547

Instead of setting the data context of each combo box manually, you should set the data context of the outer component (usually the window, or some other “larger” component) to your view model. Then you expose two lists (ideally ObservableCollection) for your two combo boxes and bind the ItemSource properties of your combo boxes to those lists. And then, whenever the SelectedItem of your first combo box changes, you update the second list:

<StackPanel>
    <ComboBox ItemsSource="{Binding Departments}" SelectedItem="{Binding SelectedDepartment}" />
    <ComboBox ItemsSource="{Binding Users}" />
</StackPanel>
public class MainViewModel : INotifyPropertyChanged
{
    // this holds the data
    private Dictionary<string, List<string>> departmentUsers = new Dictionary<string,List<string>>();

    private List<string> departments;
    public List<string> Departments
    {
        get { return departments; }
        set
        {
            if (value != departments)
            {
                departments = value;
                OnNotifyPropertyChanged("Departments");
            }
        }
    }

    private string selectedDepartment;
    public string SelectedDepartment
    {
        get { return selectedDepartment; }
        set
        {
            if (value != selectedDepartment)
            {
                selectedDepartment = value;
                OnNotifyPropertyChanged("SelectedDepartment");

                // update users list
                Users = departmentUsers[selectedDepartment];
            }
        }
    }

    private List<string> users;
    public List<string> Users
    {
        get { return users; }
        set
        {
            if (value != users)
            {
                users = value;
                OnNotifyPropertyChanged("Users");
            }
        }
    }

    public MainViewModel()
    {
        // sample data
        departmentUsers = new Dictionary<string, List<string>>();
        departmentUsers.Add("Department 1", new List<string>() { "1.1", "1.2", "1.3" });
        departmentUsers.Add("Department 2", new List<string>() { "2.1", "2.2", "2.3", "2.4", "2.5" });
        departmentUsers.Add("Department 3", new List<string>() { "3.1", "3.2" });
        departmentUsers.Add("Department 4", new List<string>() { "4.1", "4.2", "4.3" });

        // initial state
        Departments = new List<string>(departmentUsers.Keys);
        SelectedDepartment = Departments[0];
    }

    // simple INotifyPropertyChanged implementation
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnNotifyPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

Upvotes: 3

Related Questions