WPF DataGrid source updating on cell changed
Solution 1
Yes, this is possible. Your question is basically the same as DataGrid - change edit behaviour
The code below is mostly from Quartermeister's answer but I added a DependencyProperty
BoundCellLevel that you can set when you need a DataGrid
binding to be updated when the current cell changes.
public class DataGridEx : DataGrid
{
public DataGridEx()
{
}
public bool BoundCellLevel
{
get { return (bool)GetValue(BoundCellLevelProperty); }
set { SetValue(BoundCellLevelProperty, value); }
}
public static readonly DependencyProperty BoundCellLevelProperty =
DependencyProperty.Register("BoundCellLevel", typeof(bool), typeof(DataGridEx), new UIPropertyMetadata(false));
protected override Size MeasureOverride(Size availableSize)
{
var desiredSize = base.MeasureOverride(availableSize);
if ( BoundCellLevel )
ClearBindingGroup();
return desiredSize;
}
private void ClearBindingGroup()
{
// Clear ItemBindingGroup so it isn't applied to new rows
ItemBindingGroup = null;
// Clear BindingGroup on already created rows
foreach (var item in Items)
{
var row = ItemContainerGenerator.ContainerFromItem(item) as FrameworkElement;
row.BindingGroup = null;
}
}
}
Solution 2
Apply the UpdateSourceTrigger=LostFocus
to each binding. It worked like a charm for me.
<DataGridTextColumn Header="Name" Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
Solution 3
The code in the accepted answer didn't work for me since the row fetched from ItemContainerGenerator.ContainerFromItem(item)
results in null and the loop be quite slow.
A more simple solution to the question is the code provided here: http://codefluff.blogspot.de/2010/05/commiting-bound-cell-changes.html
private bool isManualEditCommit;
private void HandleMainDataGridCellEditEnding(
object sender, DataGridCellEditEndingEventArgs e)
{
if (!isManualEditCommit)
{
isManualEditCommit = true;
DataGrid grid = (DataGrid)sender;
grid.CommitEdit(DataGridEditingUnit.Row, true);
isManualEditCommit = false;
}
}
Solution 4
Almund is right. UpdateSourceTrigger=LostFocus
will work best in you case. And as you have mentioned that your source is updating when you move to next row, that means I guess, you are using ObservableCollection<T>
to bind your DataGrid
's ItemSource
. Because that is what which you need to achieve what you want.
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity,
Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
<DataGridTextColumn Header="Total Price" Binding="{Binding TotalPrice,
Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
You need to add "UpdateSourceTrigger=LostFocus"
to each of your columns.
Related videos on Youtube
Khaled
Updated on July 09, 2022Comments
-
Khaled 11 months
I am new to the WPF ,and i use it to build a point of sale system.
I have a
DataGrid
control in the main window bound to anObservableCollection
ofItem
, the cashier will enter/scan the items to be sold the default quantity for each item is 1 but it is available for the cashier to change the quantity manually.Whenever I change the quantity, it should update the total price with the sum of the items' prices when I leave the cell to another cell on the row, but it doesn't happen, the source is updated only when I go to another row not another cell in the same row.
Is there anyway to force the
DataGrid
to update the source when the cell is changed rather than the row? -
retanik almost 10 years+1 Better solution of problem stated. Other cell values should be updated as soon as focus is lost on the cell instead of when focus is lost on the row (default).
-
Mageician almost 10 yearsExactly what I needed! Thanks!
-
Jamaxack over 7 yearsGreat! Also UpdateSourceTrigger=PropertyChanged works right after changing cell.
-
RackM about 5 yearsThis must be the solution
-
LuckyLuke82 over 2 yearsI have been struggling with this one. Should be accepted as answer.