Search code examples
c#wpfdata-bindingcomboboxdatatemplate

ComboBox binding to select item based on equality of properties of two sources when using datatemplate


Please note:

  • The two types in the lists are simplified a lot for this example and must be kept separate.

  • The use of an int as connection between the types can not be changed.

The problem:

Given the code below, how do I get the ComboBox marked with ??? to:

  • Display the ColorDefs.Name as its content.

  • Set SelectedItem to the one where Models.DisplayColorNumber is equal to ColorDefs.ColorNumber.

  • Update the Models.DisplayColorNumber updated if the selection is changed.

In code-behind

public List<ModelData> Models { get; }
public List<DisplayColorDefinition> ColorDefs { get; }

DataContext=this;

XAML:

<ListBox ItemsSource="{Binding Models}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <ComboBox ??? />
                <TextBlock Text="{Binding Models, Path=Name}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

ModelData type:

public class ModelData
{
    private string name;
    private int displayColorNumber;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }
    public int DisplayColorNumber
    {
        get { return displayColorNumber; }
        set { displayColorNumber = value; }
    }
}

DisplayColorDefinition type:

public class DisplayColorDefinition
{
    private int colorNumber;
    private string name;
    private Color displayColor;

    public int ColorNumber
    {
        get { return colorNumber; }
        set { colorNumber= value; }
    }

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public Color DisplayColor
    {
        get { return displayColor; }
        set { displayColor = value; }
    }
}

Solution

  • Use the SelectedValue and SelectedValuePath :

    <ListBox ItemsSource="{Binding Models}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <ComboBox ItemsSource="{Binding Path=DataContext.ColorDefs, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                                DisplayMemberPath="Name"
                                SelectedValue="{Binding Path=DisplayColorNumber}"
                                SelectedValuePath="ColorNumber"
                                />
                    <TextBlock Text="{Binding Name}" />
                    <TextBlock Text="{Binding DisplayColorNumber}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    SelectedValue will be the property on the Model object, and SelectedValuePath will indicate which property of the DisplayColorDefinition to use for the binding.