Problems doing NUnit test of DataGrid with data binding

Oct 20, 2008 at 12:06 PM
We do basic NUnit testing of our dialog boxes, consisting of WPF controls, using data bindings to properties on a source object:
 - We set up the source object
 - We open the dialog
 - We go through the Controls in the dialog and check that they display the correct value, e.g. compare the Text properties of TextBoxes with the source object property value bound to the Control
 - We then go through the control and change their properties to emulate user input and test that the updated values make it into the source object's properties (we e.g. set the Text properties of TextBoxes or set the Text propertie or the SelectedIndex property of ComboBoxes)

This works for basic controls of the type CheckBox, TextBox and ComboBox.  But I haven't been able to make it work for DataGrid controls bound to IList<T> properties on the source object.

What I first did to access the cell controls, and attempt to modify them, was
   DataGrid tupleGrid = (DataGrid) grid.Children[25]; // The controls of the dialog are laid out in a Grid
    DataGridColumn tupleGridFirstColumn = tupleGrid.Columns[0];
    TextBlock tupleGridCellControl = (TextBlock)tupleGridFirstColumn.GetCellContent(cells[0].Item);
    string aNewTextValue = "This a new value to put in a cell";
    tupleGrid.CurrentCell = cells[0];
    tupleGrid.BeginEdit();
    tupleGridCellControl.Text = aNewTextValue;
    tupleGrid.CommitEdit();
   Assert.AreEqual(aNewTextValue, op.AListOfStucts[0].AStringValueThatBecomesTheColumnHeader, "The new string value set on the DataGrid cell control, should have been transferred to the equivalent list item of the bound operator property");

Unfortunately the test fails because the value in the list property member is the original value.

I debugged this into 
> WPFToolkit.dll!Microsoft.Windows.Controls.DataGrid.EndEdit(System.Windows.Input.RoutedCommand command = {System.Windows.Input.RoutedCommand}, Microsoft.Windows.Controls.DataGridCell cellContainer = {Microsoft.Windows.Controls.DataGridCell: fdfsfds}, Microsoft.Windows.Controls.DataGridEditingUnit editingUnit = Row, bool exitEditMode = true) Line 2448 C#
  WPFToolkit.dll!Microsoft.Windows.Controls.DataGrid.OnCurrentCellChanged(System.Windows.DependencyObject d = {Microsoft.Windows.Controls.DataGrid Items.Count:3}, System.Windows.DependencyPropertyChangedEventArgs e = {System.Windows.DependencyPropertyChangedEventArgs}) Line 2116 + 0x1d bytes C#
[snip!]

But I was unable to debug any deeper than the line:
        command.Execute(editingUnit, cellContainer);

Based on how running the dialog seemed to upgrade the source object's list property I modified the test to change cell, to trigger the update:
    string aNewTextValue = "This a new value to put in a cell";
    tupleGrid.CurrentCell = cells[0];
    tupleGrid.BeginEdit(); // I've tried both with and without calling this method it didn't seem to make any difference
    tupleGridCellControl.Text = aNewTextValue;
    tupleGrid.CurrentCell = cells[1]; // Switching to a new cell update the source value of the previous cell
   Assert.AreEqual(aNewTextValue, op.AListOfStucts[0].AStringValueThatBecomesTheColumnHeader, "The new string value set on the DataGrid cell control, should have been transferred to the equivalent list item of the bound operator property");

Does anyone know what's the proper way of modifying the control, so that the update of the source will take place as it does during user interaction?

Thanx!
Oct 20, 2008 at 1:01 PM
Found it.

It has to do with the point in time I get the cell control.  I have to get the control, after the BeginEdit() call has been made, because that's the point in time when the _currentCellContainer() changes from null to something that holds what looks to be the right Control.  Also the Control changes from a TextBlock to a TextBox.  The code now looks like this, and the assert doesn't fail:
    string aNewTextValue = "This a new value to put in a cell";
    tupleGrid.CurrentCell = cells[0];
    tupleGrid.BeginEdit();
    TextBox tupleGridCellControl = (TextBox) tupleGridFirstColumn.GetCellContent(cells[0].Item);
    tupleGridCellControl.Text = aNewTextValue;
    tupleGrid.CurrentCell = cells[1]; // Switching to a new cell update the source value of the previous cell
    BindingExpression bindexp = tupleGrid.GetBindingExpression(ItemsControl.ItemsSourceProperty);
    Assert.AreEqual(aNewTextValue, op.AListOfStucts[0].AStringValueThatBecomesTheColumnHeader, "The new string value set on the DataGrid cell control, should have been transferred to the equivalent list item of the bound operator property");