Search code examples
wpfdatasetdatagridcomboboxcolumn

Binding a DataGridComboBoxColumn to a DataSet in WPF


I've visited a lot of topics about it but I still can't find out what the solution to my problem is, I can't re-use what I find.

I've created a DataSet which is filled by an SQL query on 2 tables. They both have a common field tough, but no foreign key (don't ask me, I can't change that) :

SELECT table1.reference, table2.reference, table1.category...
FROM table1, table2
WHERE table1.reference = table2.reference
...
dataAdapter.Fill(dataSetGrid, "table1");

My DataContext is correct, my DataSet is filled (I checked it) with correct values, I set the ItemsSource of the DataGrid by :

this.grid1.ItemsSource = dataSetGrid.Tables[0].DefaultView;

And then I tried a lot of things but the best I could get is the first element in my ComboBox but with 1 letter of each row.

One of my tests in the Xaml code :

<DataGridComboBoxColumn Header="Caméras"
                        x:Name="Cameras"
                        ItemsSource="{Binding article}"
                        SelectedValuePath="reference"
                        DisplayMemberPath="reference"
                        Width="*"/>

This one gives me an empty comboBox, but I've no problem in a DataGridTextColumn.

It works with an ObservableCollection of a class but I wish I could use a dataSet for now (performances increased).

Thanks for your help, and sorry if I missed something obvious.


Solution

  • After two days smashing my head against those really weird controls, I finally found out the solution. Actually I found some pieces of code which could have fit well with my problem, I just needed the right context. I am sure I didn't get perfectly how bindings work with comboBoxes, but here's my solution :

    Code behind :

    Data data = new Data();
    this.DataContext = data;
    this.gridCameras.ItemsSource = data.dataSetCameras.Tables[0].DefaultView;
    

    Xaml :

    <DataGridTemplateColumn Header="Cameras">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding reference}"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
        <DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
                <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.dataSetCameras.Tables[0].DefaultView}"
                          SelectedItem="{Binding article}"
                          SelectedValue="reference"
                          DisplayMemberPath="reference"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>
    </DataGridTemplateColumn>
    

    Where 'reference' is the field's name in the table in the DataSet, and 'article' the name of the table I want to bind.

    I still don't know why it works with 'AncestorType={x:Type Window}' since I'm in a userControl, and I never understand when I should use "something" instead of "{Binding something}" in the properties, or what is the real difference between "Path=" and "{Binding}", but I think that "DataContext.dataSet" allowed me to get a result, as only "dataSet" doesn't seem to work.

    Anyway, I did some tests, and it's much faster to use a DataSet than an ObservableCollection of Class in my case (more than 400 references), but I certainly missed something to get it lighter.

    Hope that helps for others !