开发者

WPF DataGrid source updating on cell changed

I am new to the WPF ,and i use it to build a point of sale system.

I have a DataGrid control开发者_如何学C 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?


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

<DataGridTextColumn Header="Name" Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />


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;
 }
}


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;
        }
    }
}


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.


For autogenerated columns the following code works:

private void ExcludeTable_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    if (e.Column is DataGridCheckBoxColumn column && column.Binding is System.Windows.Data.Binding binding)
    {
        binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜