Search code examples
wpfxamldata-binding

Bind WPF DataGridTemplateColumnn ComboBox after page had loaded


I am having problems binding to a DataGridTemplateColumn column on my control. I've read several posts about this, but none seem to be working properly for me, possibly because of the application architecture - I'm not sure. Binding to the DataGridTextColumn works, but the ComboBox I have defined inside the template column is blank. I have this XAML snippet::

    <jibcontrols:JibGrid x:Name="UsersDataGrid">
...
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox Text="{Binding Path=Role}" ItemsSource="{Binding Item, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}, Mode=FindAncestor}}" DisplayMemberPath="Role"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Width="2*" Binding="{Binding Role}"></DataGridTextColumn>
...

We are using a message bus architecture, so the data source is not ready when the page initially loads. After the data is returned from the service, a method is called to populate the DataGrid:

    private void UpdateGrid(Users o)
    {
        Dispatcher.Invoke(() =>
        {
            var entities = o.OrderBy(e => e.Role);

            UsersDataGrid.FilteredItemsSource = entities;
            UsersDataGrid.DataContext = entities;
        });
    }

What have I gotten wrong in this scenario?


Solution

  • I looked through a tutorial and saw what I was doing wrong. There were a couple things, but how I resolved it was creating a custom class with the values I needed (there were only two):

    public class RoleList : List<string>
    {
        public RoleList()
        {
            this.Add("Administrator");
            this.Add("Operator");
        }
    }
    

    Next, I added the namespace where the class resided:

    xmlns:dm="clr-namespace:Coasters.ViewModels"
    

    I then added a Page.Resources tag to hold my new data source:

    <Page.Resources>
        <dm:RoleList x:Key="RoleList" />
    </Page.Resources>
    

    Last but not least, I actually configured the ComboBox correctly (always a useful thing to do), using the ItemsSource pointing to my data source, and the SelectedItem pointing to the class property that holds the "Role" field:

            <DataGridTemplateColumn Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{StaticResource RoleList}" SelectedItem="{Binding Role}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>