web-dev-qa-db-ja.com

セルでのWPFDataGridソースの更新が変更されました

私はWPFを初めて使用し、それを使用してPOSシステムを構築します。

メインウィンドウにDataGridObservableCollectionにバインドされたItemコントロールがあります。レジ係は、販売するアイテムを入力/スキャンします。各アイテムのデフォルトの数量は1です。ただし、レジ係が手動で数量を変更することは可能です。

数量を変更するたびに、セルを行の別のセルに置いたときにアイテムの価格の合計で合計価格が更新されるはずですが、それは発生せず、ソースは別の行に移動したときにのみ更新されます同じ行の別のセルではありません。

行ではなくセルが変更されたときに、DataGridにソースを更新させる方法はありますか?

22
Khaled

はい、これは可能です。あなたの質問は基本的に DataGrid-編集動作の変更 と同じです

以下のコードは主にQuartermeisterの回答からのものですが、現在のセルが変更されたときにDependencyPropertyバインディングを更新する必要がある場合に設定できるDataGridBoundCellLevelを追加しました。

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

各バインディングにUpdateSourceTrigger=LostFocusを適用します。それは私にとって魅力のように機能しました。

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

ItemContainerGenerator.ContainerFromItem(item)からフェッチされた行がnullになり、ループが非常に遅くなるため、受け入れられた回答のコードは機能しませんでした。

質問に対するより簡単な解決策は、ここで提供されるコードです: 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;
 }
}
9
mattanja

アルムンドは正しい。 UpdateSourceTrigger=LostFocusはあなたの場合に最適です。そして、次の行に移動するとソースが更新されると述べたように、つまり、ObservableCollection<T>を使用してDataGridItemSourceをバインドしていると思います。それはあなたが望むことを達成するためにあなたが必要とするものだからです。

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

各列に"UpdateSourceTrigger=LostFocus"を追加する必要があります。

1
Mitesh