I have created a SubPODetailView.xaml that includes a SubPoDetailViewModel.cs, which in turn this Model contain a SubInvoice.cs for a datagrid and the SubPO.cs for other details. What I wnat is every time I added a row, the sum of "Amount" columns displayed in the total TextBlock.
The Screenshot of View Page of running Program
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;
}
}
}
Note: for checking the whole program as zip file, here you go(just click slow dowload then continue): http://www.filefactory.com/file/681du53ow7us/SubBVZip.zip
Update
Screenshot of the problem I got when running the program, How to sum the rows without adding another new one.