c# - 如何对 DataGridView 中添加的每个列求和?
问题描述
我创建了一个包含 SubPoDetailViewModel.cs 的SubPODetailView.xaml ,而该模型又包含用于数据网格的SubInvoice.cs和用于其他详细信息的 SubPO.cs。我想要的是每次我添加一行时,总 TextBlock 中显示的“金额”列的总和。
SubPODetailView.xaml
<DataGrid ItemsSource="{Binding Invoices}"
SelectedItem="{Binding SelectedInvoice,Mode=TwoWay}"
AutoGenerateColumns="False" RowHeaderWidth="0" >
<DataGrid.Columns>
<DataGridTextColumn Header="Invoices" Width="*"
Binding="{Binding InvoiceName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTemplateColumn Header="Date" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding Date,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Amount" Width="*" Binding="{Binding Amount,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTemplateColumn Header="Status" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Status,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<TextBlock Text="{Binding Total}" Margin="10,0" Background="#FFC9CD7D" Foreground="Black"/>
SubPODetailViewModel.cs
public class SubPODetailViewModel : DetailViewModelBase, ISubPODetailViewModel
{
private ISubPORepository _subPORepository;
private IMessageDialogService _messageDialogService;
private SubPOWrapper _subPO;
private SubInvoiceWrapper _selectedInvoice;
public SubPODetailViewModel(IEventAggregator eventAggregator,
IMessageDialogService messageDialogService,
ISubPORepository subPORepository) : base(eventAggregator)
{
_subPORepository = subPORepository;
_messageDialogService = messageDialogService;
AddInvoiceCommand = new DelegateCommand(OnAddInvoiceExecute);
RemoveInvoiceCommand = new DelegateCommand(OnRemoveInvoiceExecute, OnRemoveInvoiceCanExecute);
Invoices = new ObservableCollection<SubInvoiceWrapper>();
}
// SubPOWrapper for SubPO.cs class
public SubPOWrapper SubPO
{
get { return _subPO; }
private set
{
_subPO = value;
OnPropertyChanged();
}
}
// SubInvoiceWrapper for SubInvoice.cs class
public SubInvoiceWrapper SelectedInvoice
{
get { return _selectedInvoice; }
set
{
_selectedInvoice = value;
OnPropertyChanged();
((DelegateCommand)RemoveInvoiceCommand).RaiseCanExecuteChanged();
}
}
public ICommand AddInvoiceCommand { get; }
public ICommand RemoveInvoiceCommand { get; }
public ObservableCollection<SubInvoiceWrapper> Invoices { get; }
public override async Task LoadAsync(int? subPOId)
{
var subPO = subPOId.HasValue
? await _subPORepository.GetByIdAsync(subPOId.Value)
: CreateNewSubPO();
InitializeSubPO(subPO);
InitializeSubInvoice(subPO.Invoices);
}
private SubPO CreateNewSubPO()
{
var subPO = new SubPO();
_subPORepository.Add(subPO);
return subPO;
}
private void InitializeSubInvoice(ICollection<SubInvoice> invoices)
{
foreach (var wrapper in Invoices)
{
wrapper.PropertyChanged -= SubInvoiceWrapper_PropertyChanged;
}
Invoices.Clear();
foreach (var subInvoice in invoices)
{
var wrapper = new SubInvoiceWrapper(subInvoice);
Invoices.Add(wrapper);
wrapper.PropertyChanged += SubInvoiceWrapper_PropertyChanged;
}
}
private void SubInvoiceWrapper_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (!HasChanges)
{
HasChanges = _subPORepository.HasChanges();
}
if (e.PropertyName == nameof(SubInvoiceWrapper.HasErrors))
{
((DelegateCommand)SaveCommand).RaiseCanExecuteChanged();
}
}
private void InitializeSubPO(SubPO subPO)
{
SubPO = new SubPOWrapper(subPO);
SubPO.PropertyChanged += (s, e) =>
{
if (!HasChanges)
{
HasChanges = _subPORepository.HasChanges();
}
if (e.PropertyName == nameof(SubPO.HasErrors))
{
((DelegateCommand)SaveCommand).RaiseCanExecuteChanged();
}
};
((DelegateCommand)SaveCommand).RaiseCanExecuteChanged();
if (SubPO.Id == 0)
{
// Little trick to trigger the validation
SubPO.Title = "";
}
}
protected override void OnDeleteExecute()
{
var result = _messageDialogService.ShowOkCancelDialog($"Do you really want to delete the Subcontractor {SubPO.Title}?", "Question");
if (result == MessageDialogResult.OK)
{
_subPORepository.Remove(SubPO.Model);
_subPORepository.SaveAsync();
RaiseDetailDeletedEvent(SubPO.Id);
}
}
protected override bool OnSaveCanExecute()
{
return SubPO != null
&& !SubPO.HasErrors
&& Invoices.All(i=>!i.HasErrors)
&& HasChanges;
}
protected override async void OnSaveExecute()
{
await _subPORepository.SaveAsync();
HasChanges = _subPORepository.HasChanges();
RaiseDetailSavedEvent(SubPO.Id, SubPO.Title);
}
private void OnAddInvoiceExecute()
{
var newInvoice = new SubInvoiceWrapper(new SubInvoice());
newInvoice.PropertyChanged += SubInvoiceWrapper_PropertyChanged;
Invoices.Add(newInvoice);
SubPO.Model.Invoices.Add(newInvoice.Model);
//newInvoice.InvoiceName = "";
newInvoice.Date = DateTime.Now.Date;
// Trigger validation :-)
}
private void OnRemoveInvoiceExecute()
{
SelectedInvoice.PropertyChanged -= SubInvoiceWrapper_PropertyChanged;
_subPORepository.RemoveInvoice(SelectedInvoice.Model);
Invoices.Remove(SelectedInvoice);
SelectedInvoice = null;
HasChanges = _subPORepository.HasChanges();
((DelegateCommand)SaveCommand).RaiseCanExecuteChanged();
}
private bool OnRemoveInvoiceCanExecute()
{
return SelectedInvoice !=null;
}
}
}
注意:要检查整个程序为 zip 文件,这里你去(只需点击慢速下载然后继续):http ://www.filefactory.com/file/681du53ow7us/SubBVZip.zip
更新
运行程序时遇到的问题的屏幕截图,如何在不添加另一个新行的情况下对行求和。
解决方案
SubPODetailView 的最后一个 TextBlock 已经绑定到视图模型中的 Total 属性。在视图模型上创建属性 Total 并将 CollectionChanged 处理程序添加到 Invoices:
public SubPODetailViewModel(IEventAggregator eventAggregator,
IMessageDialogService messageDialogService,
ISubPORepository subPORepository) : base(eventAggregator)
{
...
Invoices.CollectionChanged += Invoices_CollectionChanged;
}
private void Invoices_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Total = Invoices.Sum(x => x.Amount);
}
private decimal _total;
public decimal Total
{
get => _total;
set {
_total = value;
OnPropertyChanged();
}
}
推荐阅读
- mysql - MySql 从查询中获取第一个和最后一个结果
- html - CSS中有没有一种方法可以防止寡妇,而不必使用额外的HTML?
- maven - 传递依赖不能正常工作
- python - 如何使用 Python3 和 ANTLR4 修改 java 源代码?
- python - 达到 100% 时更改条形颜色的优雅方式
- swift - 在 Swift 中为 Tensorflow 创建随机张量
- regex - 用于匹配文本中相同单词的正则表达式
- lua - “尝试使用 TweenService() 时,函数 Create 不是“UnionOperation”的成员
- ionic-framework - 在Android上点击通知时应用程序不显示
- sql - 如何检索已删除的表?