There is a button for further SQL validation, I don't want it to be performed unless user input is correct (no cells in a Datagrid are empty).
I have observed that validation raised properly only when cell already has a value and it is removed (empty again). So I have realized that it was because of the fact that it's done on PropertyChangedEvent
so if it wasn't edited so far then validation didn't occur.
To solve that problem I have wrapped ValidateAllProperties()
into a public method in OrderUploadViewModel
to access it from the parent ViewModel. However without any success.
View
<DataGrid
Grid.Row="0"
AutoGenerateColumns="False"
ColumnWidth="*"
ItemsSource="{Binding Orders, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Resources>
<Style x:Key="editStyle" TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red" />
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding CustomerId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"
EditingElementStyle="{StaticResource editStyle}"
Header="Customer Id" />
<DataGridTextColumn
Binding="{Binding DeliveryId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"
EditingElementStyle="{StaticResource editStyle}"
Header="Delivery Id" />
<DataGridTextColumn
Binding="{Binding RequestedQuantity, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"
EditingElementStyle="{StaticResource editStyle}"
Header="Requested Quantity" />
</DataGrid.Columns>
</DataGrid>
<Button
Grid.Row="1"
HorizontalAlignment="Right"
Command="{Binding ValidateCommand}"
Content="Validate" />
UploadViewModel
public IRelayCommand ValidateCommand { get; private set; }
private BindingList<OrderUploadViewModel> orders;
public BindingList<OrderUploadViewModel> Orders
{
get
{
return orders;
}
set
{
SetProperty(ref orders, value);
}
}
private readonly OrdersRepository _ordersRepository;
public UploadViewModel(OrdersRepository ordersRepository)
{
_ordersRepository = ordersRepository;
ValidateCommand = new RelayCommand(Validate, CanExecuteValidate);
Orders = new BindingList<OrderUploadViewModel>();
Orders.ListChanged += HandleOrdersChanged;
}
private void Validate()
{
IsValidated = false;
foreach (var order in Orders)
{
if(order.Validate())
{
if (!_ordersRepository.Validate(Plugin.Mapper.Map<OrderUploadViewModel, OrderUpload>(order)))
{
return;
}
}
else
{
return;
}
}
IsValidated = true;
}
private bool CanExecuteValidate()
{
return !Orders.Any(o => o.HasErrors);
}
private void HandleOrdersChanged(object sender, ListChangedEventArgs e)
{
ValidateCommand.NotifyCanExecuteChanged();
}
OrderUploadViewModel
public class OrderUploadViewModel : ObservableValidator
{
private string customerId;
[Required(ErrorMessage = "Customer Id value is required")]
public string CustomerId
{
get
{
return customerId;
}
set
{
SetProperty(ref customerId, value, validate: true);
}
}
private string deliveryId;
[Required(ErrorMessage = "Delivery Id value is required")]
public string DeliveryId
{
get
{
return deliveryId;
}
set
{
SetProperty(ref deliveryId, value, validate: true);
}
}
private string requestedQuantity;
[Required(ErrorMessage = "Requested Quantity value is required")]
public string RequestedQuantity
{
get
{
return requestedQuantity;
}
set
{
SetProperty(ref requestedQuantity, value, validate: true);
}
}
public bool Validate()
{
ValidateAllProperties();
return HasErrors;
}
}