Je suis nouveau sur WPF et je l’utilise pour construire un système de point de vente.
J'ai un contrôle DataGrid
dans la fenêtre principale lié à un ObservableCollection
de Item
, le caissier entrera/scannera les articles à vendre. La quantité par défaut pour chaque article est 1, mais le caissier peut modifier la quantité manuellement.
Chaque fois que je change la quantité, il convient de mettre à jour le prix total avec la somme des prix des articles lorsque je laisse la cellule à une autre cellule de la ligne, mais cela n'arrive pas, la source est mise à jour uniquement lorsque je passe à une autre ligne. pas une autre cellule dans la même rangée.
Est-il possible de forcer la DataGrid
à mettre à jour le source lorsque la cellule est modifiée plutôt que la ligne?
Oui, c'est possible Votre question est fondamentalement la même que DataGrid - changer le comportement de l’édition
Le code ci-dessous provient principalement de la réponse de Quartermeister, mais j'ai ajouté un DependencyProperty
BoundCellLevel que vous pouvez définir lorsque vous avez besoin d'une liaison DataGrid
à mettre à jour lorsque la cellule en cours change.
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;
}
}
}
Appliquez le UpdateSourceTrigger=LostFocus
à chaque liaison. Cela a fonctionné comme un charme pour moi.
<DataGridTextColumn Header="Name" Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
Le code de la réponse acceptée ne fonctionnait pas pour moi car la ligne extraite de ItemContainerGenerator.ContainerFromItem(item)
donnait la valeur null et que la boucle était assez lente.
Une solution plus simple à la question est le code fourni ici: 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;
}
}
Almund a raison. UpdateSourceTrigger=LostFocus
fonctionnera mieux dans votre cas. Et comme vous avez mentionné que votre source est mise à jour lorsque vous passez à la ligne suivante, cela signifie que vous utilisez probablement ObservableCollection<T>
pour lier votre DataGrid
's ItemSource
. Parce que c'est ce dont vous avez besoin pour réaliser ce que vous voulez.
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity,
Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
<DataGridTextColumn Header="Total Price" Binding="{Binding TotalPrice,
Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
Vous devez ajouter "UpdateSourceTrigger=LostFocus"
à chacune de vos colonnes.