2
votes

I have a problem with the binding of a datagrid control in net 4 wpf c# project Sorry if I have posted too much info or not enough I never guess the correct amount

This is what I have.

1.A datagrid control called dgCSVData, which has autogenerate columns ticked

my xaml is

<DataGrid ItemsSource="{Binding dgCSVData}" Name="dgCSVData" Height="283" Width="1033" IsEnabled="True" ContextMenuService.ShowOnDisabled="True" IsReadOnly="True" SelectionChanged="dgCSVData_SelectionChanged" >
    <DataGrid.ContextMenu>
        <ContextMenu>
            <MenuItem Command="Copy">
                <!--<MenuItem.Icon>
                    <Image Source="Images/copy.png" />
                </MenuItem.Icon>-->
            </MenuItem>
        </ContextMenu>
    </DataGrid.ContextMenu>
</DataGrid>
  1. I'm reading a csv into a list and using the list to create a datatable which has been cloned from my sql db. The datatable is created in a background reader and handed back to the main thread. I have cycled through the items in the tables data row and confirmed the datatable gets back with correct information: here is one row from the table outputed from debug

Year Item: 2013/14,From Item: 12/10/2013 00:00:00,To Item: 18/10/2013 00:00:00,Week No Item: 27,Clock No Item: 1139,Name Item: SINGH,Initial Item: R,Dept Item: 1,Own Hours Item: 55.50,Other Hours Item: 0.00,Total Hours Item: 55.50,O/T Premium Item: 7.92

I set (or rather try to) set the content of the datagrid with this code

void objProgress_ValueChanged(DataTable Result,string msg)
{
    //Handle the event of csv datatable ready to return
    oTable = Result;

    //this is just for debug
    DataRow Dr = oTable.Rows[0];
    foreach (var item in Dr.ItemArray)
    {
        System.Windows.Forms.MessageBox.Show(item.ToString());
    }

    //this meant to set the binding BUT DOES NOT WORK TOTALLY LAST COLUMN MISSING
    this.dgCSVData.DataContext = oTable.DefaultView;
    this.dgCSVData.ItemsSource = oTable.DefaultView;
    tbLoadDgStat.Visibility = Visibility.Visible;

    //This does some error checking
    if (oTable.Rows.Count > 1)
    {
        if (msg.Trim().StartsWith("Warning"))
        {
            System.Windows.Media.Color c = Colors.Red;

            this.tbLoadDgStat.Background = new SolidColorBrush(c);
            System.Windows.Forms.MessageBox.Show(oTable.Rows.Count.ToString());
        }

        this.tbLoadDgStat.Text = msg;
        progressBar1.Value = 100;

        btUpload.IsEnabled = true;
    }
    else
    {
        this.tbdgImport.Text = "Error no data returned";
        progressBar1.Value = 50;
    }

    System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;

    progressBar1.Visibility = Visibility.Hidden;
    this.Show();
}

The error I receive is

System.Windows.Data Error: 40 : BindingExpression path error: 'O' property not found on 'object' ''DataRowView' (HashCode=30297615)'. BindingExpression :Path=O/T Premium; DataItem='DataRowView' (HashCode=30297615) ; target element is 'TextBlock' (Name='') ; target property is 'Text' (type 'String')

The path O/T Premium is the last column of both the datatable and the datagrid. it should be from the row above a value of O/T Premium Item: 7.92 from the data table this is a decimal, but so are the four previous items that bind correctly

I'm trying to make the binding as generic as possible as I am expecting to read different csv file into the datagrid in the next stage of the development

I do not understand the binding issue as all the other items from the data table are displayed correctly and done by the two lines of code

 this.dgCSVData.DataContext = oTable.DefaultView;
        this.dgCSVData.ItemsSource = oTable.DefaultView;
2
You can't use a / character in your Binding.Path... you can see that the error says that it can't find the O property because / means something in Binding path syntax. Try renaming that column.Sheridan
@Sheridan - Thank you, as always it is the simplest thing! Data column changed in Datatable and no problemsIan W
Good, I'm glad that helped. I'm going to put my comment into an answer and request that you mark it as correct so that other users will know that this question has been answered.Sheridan
Helped me too! But I am still wondering if there is a way to use a / character as part of the column header in that scenario. A bit off-topic, but if the header contains a _ character, it will be removed.Florian

2 Answers

3
votes

You can't use a '/' character in your Binding.Path... you can see that the error says that it can't find the O property because '/' means something in Binding path syntax. Removing the the '/' charcter from the column will fix your problem.

You can find out more about the Binding.Path syntax from the Binding.Path Property page on MSDN. From the linked page:

When the source is a collection view, the current item can be specified with a slash (/). For example, the clause Path=/ sets the binding to the current item in the view. When the source is a collection, this syntax specifies the current item of the default collection view.

0
votes

Please see the comment above from @Sheridan

My problem was that / is the escape character in wpf binding see the microsoft docs here

so my data column which in sql was [O/T Premium] for my data table column when autogenerating the binding path ended up at O and hence not mapped.

After changing my sql data column in my table there was no problem.

(I guess if you can not change the data table you could rename the problem column in your sql command such as Select [O/T Premium] as [OT Premium]