13

I have a project with an XmlDataProvider bound to a WPF DataGrid control. I have the bindings on the DataGrid set up as follows:

<dg:DataGrid ItemsSource="{Binding Source={StaticResource XmlData}, XPath=Root/People/Person}"
             AutoGenerateColumns="False">
    <dg:DataGrid.Columns>
        <dg:DataGridTextColumn Header="ID" Binding="{Binding XPath=ID}"/>
        <dg:DataGridTextColumn Header="Name" Binding="{Binding XPath=Name}"/>
    </dg:DataGrid.Columns>
</dg:DataGrid>

Users can edit entries using the DataGrid without any problems. What I cannot manage to accomplish is allowing the user to add a new row (i.e. a new Person) using the DataGrid. How can I allow this?

bluepolystyreneman
  • 131
  • 1
  • 1
  • 3

4 Answers4

19

Make sure that you set: CanUserAddRows="True" and that the default constructor of a bound class is available.

Darren Young
  • 10,972
  • 36
  • 91
  • 150
Boris Lipschitz
  • 9,236
  • 5
  • 53
  • 63
3

To add a row to a WPF DataGrid that is bound to an XmlDataSource, you need to directly modify the backing data store. You can use the DataGrid to collect the new row information from the user and then in the RowEditEnding event, you can add the row's information to your backing store and prevent the DataGrid from actually trying to commit the edit using its internal logic. Since the DataGrid is bound to the XmlDataSource, it will display the changes you made to the backing store.

Here is the general idea:

private void MyDataGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
  if (e.EditAction == DataGridEditAction.Cancel)
  {
    e.Cancel = false;
    return;
  }

  if (e.EditAction == DataGridEditAction.Commit)
  {
    DataGridRow dgr = e.Row;
    XmlElement xe = myXmlDataProvider.Document.CreateElement("NewRowElement");
    foreach(DataGridCell cell in dgr.Cells)
    {
      xe.SetAttribute(cell.Name, cell.Value);
    }
    dataProvider.Document.DocumentElement.AppendChild(xe);
    e.Cancel = true;
  }
}
Timothy Lee Russell
  • 3,719
  • 1
  • 35
  • 43
  • I can't find `Cells` property from `dgr` or `DataGridRow` – Bolu Feb 28 '11 at 13:56
  • This is pre-4.0 WPF info -- I think the row and cell collections might not be public anymore? Check the Items collection. The main point of my answer, which is that you need to modify the backing data store, still holds true, I think. – Timothy Lee Russell Mar 01 '11 at 17:13
0

Is the problem that the user can't add rows or is it that when the user does add a row, it's not saved to the backing XML store? I can easily add a datagrid with CanUserAddRows="True" to a WPF application, bind the grid to an in-memory list and then have the user add rows that are reflected in that in-memory list. That makes me think that your problem is saving to the backing store.

When I bind to an XML on the file system, I can no longer add records to the data grid. I think you will need a minor workaround in that you read the file into an in-memory collection, bind to that and then update the file accordingly as users add rows.

Brett Bim
  • 3,190
  • 4
  • 28
  • 26
0

Have you tried setting CanUserAddRows="True" on the DataGrid?

user61073
  • 86
  • 5
  • 7
    I ran into this same problem today. I have explicitly set CanUserAddRows = true, but it turns to false immidiately as I found from the Immediate Window. The reason is that the binding class doesn't have a default constructor. Once I added the default constructor, I got the new row at the end. – miliu Sep 11 '10 at 22:34