Search code examples
c#wpfdatagridwpf-controls

C# WPF datagrid template column with combobox having different datasource


enter image description hereI have a window with 2 controls. One is a combobox (cmbUnit) and another is a DataGrid (dgvProducts)

cmbUnits is binded with List<Unit> collection & the Unit class is below

public class Unit
{
   public int ID { get; set; }
   public string Name { get; set; }
}

Note : Display member is Name & Value member is ID

Where as, dgvProducts is binded with List<Product> Collection & the Product class is below

public class Product
{
       public int ID { get; set; }
       public string ProductName { get; set; }
       public int UnitID { get; set; }
}

Here, i am selecting UnitID from my db table (TBL_PRODUCTS), I can also retrieve UnitName by joining table. for now, i want to keep only UnitID in my Product class.

My question is, My datagrid has a column (datagridTemplateColumn) with a combobox as the child, and i want to show the UnitName inside it by passing UnitID same like my combobox control (cmbUnit)

My Datas inside datagrid should be

--------------------------------------------------
ID      UnitName     ProductName
--------------------------------------------------
12345    Kg         Sample Product

Where Kg should be displayed inside a combobox. How to achieve this ? Help me !

My XAML code for cmbUnit is

<ComboBox Grid.Column="7" Grid.Row="1" Name="cmbUnit" ></ComboBox>

where i bind datas to this control from code behind.

XAML for dgvProducts

<DataGrid AutoGenerateColumns="False" Grid.ColumnSpan="2"
              Name="dgvProduct"  
              Grid.Row="2">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="ID" Width="50" CanUserSort="True">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label VerticalContentAlignment="Center" Content="{Binding ID}"></Label>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Unit" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox IsEnabled="False"
                            Name="cmbGrUnit"
                            ItemsSource="{Binding Units}"
                            DisplayMemberPath="Name"
                            SelectedValuePath="ID"
                            SelectedValue="{Binding UnitID}"
                            ></ComboBox>
                        <!--<Label VerticalContentAlignment="Center" Content="{Binding Name}"></Label>-->
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Product Name" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label VerticalContentAlignment="Center" Content="{Binding ProductName}"></Label>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn></DataGrid.Columns>

Thanks


Solution

  • When you have

    <ComboBox Grid.Column="7" Grid.Row="1" Name="cmbUnit" ></ComboBox>
    

    With ItemsSource set from code behind

    cmbUnit.ItemsSource = this.Units
    

    then you can use this cmbUnit as a source object for your binding in the following way:

    <DataGridTemplateColumn Header="Unit" Width="*">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox ItemsSource="{Binding Path=ItemsSource, ElementName=cmbUnit}"
                        SelectedValuePath="ID" DisplayMemberPath="Name" SelectedValue="{Binding Path=UnitID}" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    

    Note, that ComboBox inside DataGrid have its own DataContext, which contains an element of your DataGrid's ItemsSource. Also, it is part of DataTemplate, which means it is not an object itself, so you cannot bind directly to it from code behind.