Обновлено исходное обновление WPF DataGrid на ячейке
Я новичок в WPF, и я использую его для создания системы продаж.
У меня есть элемент управления DataGrid
в главном окне, привязанный к ObservableCollection
от Item
, кассир войдет/сканирует предметы, которые будут проданы. Значение по умолчанию для каждого элемента равно 1, но оно доступно для кассир, чтобы вручную изменить количество.
Всякий раз, когда я изменяю количество, он должен обновлять общую цену с суммой цен товаров, когда я оставляю ячейку в другой ячейке в строке, но этого не происходит, источник обновляется только тогда, когда я иду в другую строку, а не другую ячейку в той же строке.
Есть ли способ заставить DataGrid
обновить источник, когда ячейка изменена, а не строка?
Ответы
Ответ 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"
в каждый из столбцов.