Подтвердить что ты не робот

Обновлено исходное обновление WPF DataGrid на ячейке

Я новичок в WPF, и я использую его для создания системы продаж.

У меня есть элемент управления DataGrid в главном окне, привязанный к ObservableCollection от Item, кассир войдет/сканирует предметы, которые будут проданы. Значение по умолчанию для каждого элемента равно 1, но оно доступно для кассир, чтобы вручную изменить количество.

Всякий раз, когда я изменяю количество, он должен обновлять общую цену с суммой цен товаров, когда я оставляю ячейку в другой ячейке в строке, но этого не происходит, источник обновляется только тогда, когда я иду в другую строку, а не другую ячейку в той же строке.

Есть ли способ заставить DataGrid обновить источник, когда ячейка изменена, а не строка?

4b9b3361

Ответ 1

Да, это возможно. Ваш вопрос в основном такой же, как DataGrid - изменение поведения редактирования

Ниже приведен код в основном из ответа Quartermeister, но я добавил DependencyProperty BoundCellLevel, который вы можете установить, когда вам понадобится привязка DataGrid, которая будет обновляться при изменении текущей ячейки.

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

Ответ 2

Примените UpdateSourceTrigger=LostFocus к каждой привязке. Это работало как прелесть для меня.

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

Ответ 3

Код в принятом ответе не работал у меня, так как строка, полученная из ItemContainerGenerator.ContainerFromItem(item), возвращает нуль, и цикл будет довольно медленным.

Более простым решением вопроса является приведенный здесь код: 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;
 }
}

Ответ 4

Альмунд прав. UpdateSourceTrigger=LostFocus будет работать лучше всего в вашем случае. И, как вы уже упоминали, ваш источник обновляется, когда вы переходите к следующей строке, это означает, что я полагаю, вы используете ObservableCollection<T> для привязки вашего DataGrid ItemSource. Потому что это то, что вам нужно для достижения того, чего вы хотите.

<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity,
                    Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
<DataGridTextColumn Header="Total Price" Binding="{Binding TotalPrice,
                    Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />

Вам нужно добавить "UpdateSourceTrigger=LostFocus" в каждый из столбцов.