DataGrid仅检测用户所做的更改

时间:2017-08-10 08:01:41

标签: c# wpf datagrid

我有一个财务应用程序,用户可以在其中输入发票金额到DataGrid中。 DataGrid绑定了一个ObservableCollection金额,每个金额由Gross,VAT rate,VAT和Net组成。要求是每当用户输入四个值中的两个时,另外两个将由软件计算并显示。因此,对于每个列,CellEditEnding事件(增值税率为SelecChanged,这是一个ComboBox)上有一个事件处理程序,当用户更改它们的值时,它应该触发。

我的问题是,事件不仅触发用户交互,而且总是在值发生变化时触发,例如作为计算的结果。有没有办法只检测用户所做的更改,即仅在用户更改值时才触发事件?

以下是代码:

XAML

<DataGrid 
    x:Name="dgvBetraege"
    Grid.Row="3"
    Grid.Column="1"
    Grid.ColumnSpan="2"
    Focusable="True"
    TabIndex="3"
    Margin="0,0,0,3"
    ItemsSource="{Binding currEinnahme.Betraege, Mode=TwoWay}"
    IsSynchronizedWithCurrentItem="True"
    AlternationCount="2"
    RowHeight="24"
    AlternatingRowBackground="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
    HorizontalGridLinesBrush="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
    VerticalGridLinesBrush="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
    SelectionMode="Single"
    SelectionUnit="FullRow"
    SelectedItem="{Binding currBetrag, Mode=TwoWay}"
    AutoGenerateColumns="False"
    VerticalAlignment="Stretch"
    HorizontalAlignment="Stretch"
    RenderTransformOrigin="0.5,0.5"
    CanUserAddRows="False"
    HeadersVisibility="Column"
    VerticalScrollBarVisibility="Hidden"
    HorizontalScrollBarVisibility="Disabled"
    CellEditEnding="Betrag_CellEditEnding">

    <DataGrid.Columns>

        <DataGridTextColumn 
            Binding="{Binding Path=BetragID}"
            Visibility="Hidden">
        </DataGridTextColumn>

        <DataGridTextColumn 
            x:Name="colBetBtto"
            Header="Brutto"
            HeaderStyle="{StaticResource DataGridHeaderRightAligned}"
            Width="*"
            CellStyle="{StaticResource DataGridCellRightAligned}"
            Binding="{Binding Path=BttoBetrag, Mode=TwoWay, StringFormat=N2, UpdateSourceTrigger=PropertyChanged}">
        </DataGridTextColumn>

        <DataGridTemplateColumn 
            x:Name="colBetUSt"
            Header="USt %"
            HeaderStyle="{StaticResource DataGridHeaderRightAligned}"
            Width="*">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate DataType="mod:UStSatz">
                    <ComboBox 
                        ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.UStSaetze, Mode=OneWay}"
                        DisplayMemberPath="UStProz"
                        HorizontalAlignment="Stretch"
                        TextBlock.TextAlignment="Right"
                        ItemStringFormat="{}{0,19:N1} %"
                        SelectedItem="{Binding USt, Mode=TwoWay, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged}"
                        SelectionChanged="ComboBox_SelectionChanged">
                    </ComboBox>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

        <DataGridTextColumn 
            x:Name="colBetUStB"
            Header="USt"
            HeaderStyle="{StaticResource DataGridHeaderRightAligned}"
            Width="*"
            CellStyle="{StaticResource DataGridCellRightAligned}"
            Binding="{Binding Path=UStBetrag, Mode=TwoWay, StringFormat=N2, UpdateSourceTrigger=PropertyChanged}">
        </DataGridTextColumn>

        <DataGridTextColumn 
            x:Name="colBetNtto"
            Header="Netto"
            HeaderStyle="{StaticResource DataGridHeaderRightAligned}"
            Width="*"
            CellStyle="{StaticResource DataGridCellRightAligned}"
            Binding="{Binding Path=NttoBetrag, StringFormat=N2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
        </DataGridTextColumn>

    </DataGrid.Columns>

代码背后:

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ComboBox s = (ComboBox)e.Source;
    vmEinnahme.CalculateBetrag((int)enumBetColIndex.UstSatz);
    e.Handled = true;
}

private void Betrag_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    vmEinnahme.CalculateBetrag(e.Column.DisplayIndex);
}

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

您可以在进行计算时分离CellEditEnding,并在进行计算时将其附加。如果以这种方式执行此操作,则在更改计算中的值时不会触发CellEditEnding事件。

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    dgvBetraege.CellEditEnding -= Betrag_CellEditEnding;

    ComboBox s = (ComboBox)e.Source;
    vmEinnahme.CalculateBetrag((int)enumBetColIndex.UstSatz);

    dgvBetraege.CellEditEnding += Betrag_CellEditEnding;
    e.Handled = true;
}

private void Betrag_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    dgvBetraege.CellEditEnding -= Betrag_CellEditEnding;

    vmEinnahme.CalculateBetrag(e.Column.DisplayIndex);

    dgvBetraege.CellEditEnding += Betrag_CellEditEnding;
}

修改

另一种解决方案是使用bool来区分用户和程序操作。可能看起来像这样。

private bool _isCalculating = false;

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    _isCalculating = true;

    ComboBox s = (ComboBox)e.Source;
    vmEinnahme.CalculateBetrag((int)enumBetColIndex.UstSatz);

    _isCalculating = false;

    e.Handled = true;
}

private void Betrag_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    if(!_isCalculating)
    {
        vmEinnahme.CalculateBetrag(e.Column.DisplayIndex);
    }
}