0

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;
    }
}
James0n
  • 45
  • 5
  • Validate method in `OrderUploadViewModel` was supposed to return negation of `HasErrors`. Works fine now. – James0n Mar 16 '23 at 11:58

0 Answers0