Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Bind data to DataGridComboBoxColumn in DataGrid using MVVM

This is driving me crazy. I have a DataGrid which has a DataGridComboBoxColumn which I want the user to be able to use to select from. This is the basic outline of my grid.

<DataGrid ItemsSource="{Binding GoalList}" DockPanel.Dock="Bottom" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridComboBoxColumn ItemsSource="{Binding LifeAreaList}" Header="Life Area"/>
<DataGrid.Columns>
</DataGrid>

The DataGrid is bound to a collection of objects of type Goal. Each Goal has a property of type LifeArea. Each LifeArea has the properties LifeAreaId and Name.

The data context contains an observable collection of Goals: GoalList and a list of Life Areas: LifeAreaList. I want the user to be able to select a different life area for a goal. Also the name of the life area needs to be the displayed value.

EDIT


The solution is that the ItemsSource for the DataGridComboBoxColumn has to be set as a static resource. Another option is to set the ItemsSource through code.

In the end I have:

<DataGridComboBoxColumn x:Name="_lifeAreaComboBoxColumn" SelectedItemBinding="{Binding LifeArea}" DisplayMemberPath="Name" Header="Life Area">

In the code behind I set the ItemsSource:

_lifeAreaComboBoxColumn.ItemsSource = LifeAreaDAL.GetLifeAreas();

When I get a chance I'll convert this to a StaticResource.

like image 519
GoalMaker Avatar asked Aug 25 '10 06:08

GoalMaker


3 Answers

You need to do something like this (don't shoot the messenger):

<DataGridComboBoxColumn Header="Life Area" SelectedItemBinding="{Binding SelectedLifeArea}">
    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding LifeAreaList}"/>
            <Setter Property="IsReadOnly" Value="True"/>
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
    <DataGridComboBoxColumn.EditingElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding LifeAreaList}"/>
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
like image 143
Kent Boogaart Avatar answered Nov 11 '22 10:11

Kent Boogaart


In addition to binding your SelectedItem, I am guessing that your SelectedLifeArea property is not obtained directly from LifeAreaList so when comparing the two values they are returning false, even if the name and id match. You probably need to overwrite the .Equals function of the LifeArea object to return true if the Ids of both objects match

public override bool Equals(object obj)
{
    if (obj is LifeArea)
    {
        return this.Id == (obj as LifeArea).Id;
    }
    return false;
}
like image 34
Rachel Avatar answered Nov 11 '22 10:11

Rachel


Up can also use a DataGridTemplateColumn and just put a ComboBox in it and then wire the appropriate events to it.

<DataGridTemplateColumn Header="Alpha">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate DataType="models:MyModelDescription">
            <ComboBox ItemsSource="{Binding AlphaLevels, Mode=OneWay}" SelectedItem="{Binding Alpha, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged}"></ComboBox>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
like image 1
Joshua Avatar answered Nov 11 '22 09:11

Joshua