Search code examples
c#wpfdata-bindingcomboboxcaliburn.micro

Caliburn micro Binding Combobox in a listbox


I have this close to what I want to achieve but not quite. I would like to the combobox to display all departments, but only display the department that is bound to the employee. Hopefully someone can see where my error lies. New to WPF and Caliburn.

Here is my models:

public class Department
{
    public int IdDept { get; set; }
  public string NameDept { get; set; }
}
  public class Employee
{
    public int IdEmployee { get; set; }
    public string NameEmployee { get; set; }
    public int DeptId { get; set; }
}

ViewModel:

 public class ShellViewModel : PropertyChangedBase
{
    private BindableCollection<Employee> _employees = new BindableCollection<Employee>();
    private BindableCollection<Department> _departments= new BindableCollection<Department>();
    public BindableCollection<Employee> Employees
    {
        get{return _employees;}
        set
        { _employees = value; NotifyOfPropertyChange(() => Employees);}
    }
    public BindableCollection<Department> Departments
    {
        get{return _departments;}
        set{_departments = value;
            NotifyOfPropertyChange(() => Departments);}
    }

    public ShellViewModel()
    {// simulated data from DB
        Employees.Add(new Employee { IdEmployee = 1, NameEmployee = "Jim", DeptId = 1 });
        Employees.Add(new Employee { IdEmployee = 2, NameEmployee = "Mike", DeptId = 3 });

        Departments.Add(new Department { IdDept = 1, NameDept = "Accounting" });
        Departments.Add(new Department { IdDept = 2, NameDept = "Human Resource" });
        Departments.Add(new Department { IdDept = 2, NameDept = "IT" });
    }
}

}

View:

<Grid>
    <ListBox x:Name="Employees" HorizontalAlignment="Left" Height="260" Margin="83,52,0,0" VerticalAlignment="Top" Width="612">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50"/>
                            <ColumnDefinition Width="50"/>
                            <ColumnDefinition Width="50"/>
                            <ColumnDefinition Width="50"/>
                        </Grid.ColumnDefinitions>
                        <TextBox Text="{Binding NameEmployee}" Grid.Column="1" />
                    <TextBlock Text="{Binding IdEmployee}" Grid.Column="0"/>
                    <ComboBox Grid.Column="2"
                              ItemsSource="{Binding DataContext.Departments,
                        RelativeSource={RelativeSource Mode=FindAncestor,
                        AncestorType={x:Type Window}}}"
                              SelectedValuePath="DeptId"
                              DisplayMemberPath="NameDept"
                              SelectedValue="{Binding IdDept}"/>
                    </Grid>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

</Grid>


Solution

  • switch property names in SelectedValuePath and SelectedValue binding:

    SelectedValuePath="IdDept"
    SelectedValue="{Binding DeptId}"
    

    SelectedValuePath should be a property which exists in ComboBox.ItemsSource elements - thus Department.IdDept

    SelectedValue should be a property which exists in ComboBox DataContext (Employee object) - thus Employee.DeptId