C# WPF实现DataGrid行值变化时动态更新总金额文本框
动态计算DataGrid行Value总和并实时更新总金额的实现方案
核心思路是借助ObservableCollection<T>的集合变化通知能力,结合实体类的INotifyPropertyChanged事件,实时监听行数据的修改、新增和删除操作,自动计算所有行Value列的总和并同步到总金额文本框。
1. 完善实体类的INotifyPropertyChanged实现
确保业务实体完整实现接口,保证属性变更能通知到UI:
public class WorkItem : INotifyPropertyChanged { private double _unitPrice; private double _hours; public double UnitPrice { get => _unitPrice; set { _unitPrice = value; OnPropertyChanged(nameof(UnitPrice)); OnPropertyChanged(nameof(Value)); } } public double Hours { get => _hours; set { _hours = value; OnPropertyChanged(nameof(Hours)); OnPropertyChanged(nameof(Value)); } } public double Value => UnitPrice * Hours; public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
注:Value属性可简化为只读计算属性,无需私有字段,因为它完全由UnitPrice和Hours推导而来。
2. ViewModel层实现总和计算逻辑
ViewModel需要维护DataGrid的数据源,并监听集合和元素的变更事件:
public class MainViewModel : INotifyPropertyChanged { private ObservableCollection<WorkItem> _workItems; private double _totalAmount; public ObservableCollection<WorkItem> WorkItems { get => _workItems; set { if (_workItems != null) { _workItems.CollectionChanged -= WorkItems_CollectionChanged; UnsubscribeItemEvents(_workItems); } _workItems = value; if (_workItems != null) { _workItems.CollectionChanged += WorkItems_CollectionChanged; SubscribeItemEvents(_workItems); } CalculateTotal(); OnPropertyChanged(nameof(WorkItems)); } } public double TotalAmount { get => _totalAmount; set { _totalAmount = value; OnPropertyChanged(nameof(TotalAmount)); } } public MainViewModel() { WorkItems = new ObservableCollection<WorkItem>(); } private void WorkItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: if (e.NewItems != null) SubscribeItemEvents(e.NewItems.Cast<WorkItem>()); break; case NotifyCollectionChangedAction.Remove: if (e.OldItems != null) UnsubscribeItemEvents(e.OldItems.Cast<WorkItem>()); break; case NotifyCollectionChangedAction.Reset: UnsubscribeItemEvents(_workItems); break; } CalculateTotal(); } private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(WorkItem.Value)) CalculateTotal(); } private void SubscribeItemEvents(IEnumerable<WorkItem> items) { foreach (var item in items) item.PropertyChanged += Item_PropertyChanged; } private void UnsubscribeItemEvents(IEnumerable<WorkItem> items) { foreach (var item in items) item.PropertyChanged -= Item_PropertyChanged; } private void CalculateTotal() { TotalAmount = WorkItems.Sum(item => item.Value); } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
3. XAML绑定配置
在视图中绑定DataGrid和总金额文本框,确保输入时实时更新:
<!-- DataGrid配置 --> <DataGrid ItemsSource="{Binding WorkItems}" AutoGenerateColumns="False" CanUserDeleteRows="True"> <DataGrid.Columns> <DataGridTextColumn Header="单价" Binding="{Binding UnitPrice, UpdateSourceTrigger=PropertyChanged}" /> <DataGridTextColumn Header="时长" Binding="{Binding Hours, UpdateSourceTrigger=PropertyChanged}" /> <DataGridTextColumn Header="金额" Binding="{Binding Value}" IsReadOnly="True" /> </DataGrid.Columns> </DataGrid> <!-- 总金额显示 --> <StackPanel Orientation="Horizontal" Margin="10 0"> <TextBlock Text="总金额:" VerticalAlignment="Center"/> <TextBox Text="{Binding TotalAmount, Mode=OneWay}" IsReadOnly="True" Width="100" Margin="5 0"/> </StackPanel>
关键说明
ObservableCollection<T>:负责通知集合的增、删、重置操作,是实现行删除后自动扣减总和的核心- 元素事件订阅:给每个新增的
WorkItem订阅PropertyChanged事件,监听Value属性变化,实现输入单价/时长时实时更新总和 UpdateSourceTrigger=PropertyChanged:确保输入框内容变化时立即更新源属性,触发后续的计算逻辑- 内存泄漏防护:移除元素时取消订阅其
PropertyChanged事件,避免内存泄漏
内容的提问来源于stack exchange,提问作者Tharindu
相关产品推荐
相关产品推荐

