WPF DataGrid source updating on cell changed

2019-02-02 06:38发布

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 an ObservableCollection of Item, 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?

4条回答
姐就是有狂的资本
2楼-- · 2019-02-02 07:10

Apply the UpdateSourceTrigger=LostFocus to each binding. It worked like a charm for me.

<DataGridTextColumn Header="Name" Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
查看更多
手持菜刀,她持情操
3楼-- · 2019-02-02 07:19

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;
 }
}
查看更多
Luminary・发光体
4楼-- · 2019-02-02 07:22

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.

查看更多
成全新的幸福
5楼-- · 2019-02-02 07:25

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;
        }
    }
}
查看更多
登录 后发表回答