<DataGrid Name="DataGrid" Binding={Binding} CurrentCellChanged="DataGrid_CurrentCellChanged">
<DataGrid.Columns>
<DataGridTextColumn x:Name="Quantity" Header="Qty"/>
<DataGridTextColumn x:Name="UnitPrice" Header="Unit Price"/>
<DataGridTextColumn x:Name="ExtPrice" Header="Ext. Price" IsReadOnly="true"/>
</Columns>
</DataGrid>
Private Sub DataGrid_CurrentCellChanged(Sender as Object, e as EventArgs)
try
Dim Q as double = DataGrid.SelectedItem("Quantity")
Dim U as double = DataGrid.SelectedItem("UnitPrice")
DataGrid.SelectedItem("ExtPrice") = Q * U
catch
end try
End Sub
When you enter a value in Quantity and tab out the CurrentCellChanged event handler is raised but when you peek inside SelectedItem you see that Quantity is empty. You can see it on the screen, but it isn't in the selected item yet. If you look around you can find UpdateSourceTrigger will allow you to control when a control updates it's backing source, but for a DataGrid the entire row is considered one control, so the backing source isn't updated until the entire row loses focus.
This isn't going to work for us because we want to update Extended Price while we're still on the row. You could use the VisualTreeManager to scrape the value out of the control without looking at the backing store but that's slow and brittle. The answer is to simply commit the datagrid in code by putting a line like this at the beginning of the event handler.
DataGrid.CommitEdit()
This causes pending edits to be updated to the backing store. It's the same thing you do when you define UpdateSourceTrigger="Explicit". Of course, if we could set UpdateSourceTrigger="CellLostFocus" on a datagrid we could avoid this, but we can't.
No comments:
Post a Comment