Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Cannot bind validation to a specific ViewModel property, throws NullReferenceException #16

Closed
ThomasPrioul opened this issue Mar 28, 2019 · 3 comments
Assignees
Labels
bug Something isn't working outdated

Comments

@ThomasPrioul
Copy link

I'm trying the samples adapted to a WPF project.
I copied the ViewModel sample as-is and created a WPF view with type-safe bindings like the given android sample.

ViewModel:

public class SampleViewModel : ReactiveObject, ISupportsValidation
{
    public SampleViewModel()
    {
        // Name must be at least 3 chars. The selector is the property name and the line below is
        // a single property validator.
        this.ValidationRule(
            viewModel => viewModel.Name,
            name => !string.IsNullOrWhiteSpace(name),
            "You must specify a valid name");

        // Age must be between 13 and 100, message includes the silly length being passed in,
        // stored in a property of the ViewModel.
        AgeRule = this.ValidationRule(
            viewModel => viewModel.Age,
            age => age >= 13 && age <= 100,
            age => $"{age} is a silly age");

        var nameAndAgeValid = this
            .WhenAnyValue(x => x.Age, x => x.Name, (age, name) => new { Age = age, Name = name })
            .Select(x => x.Age > 10 && !string.IsNullOrEmpty(x.Name));

        // Create a rule from an IObservable.
        ComplexRule = this.ValidationRule(
            _ => nameAndAgeValid,
            (vm, state) => !state ? "That's a ridiculous name / age combination" : string.Empty);

        // IsValid extension method returns true when all validations succeed.
        var canSave = this.IsValid();

        // Save command is only active when all validators are valid.
        Save = ReactiveCommand.CreateFromTask(async unit => { }, canSave);
    }

    [Reactive] public int Age { get; set; }

    // Declare a separate validator for age rule.
    public ValidationHelper AgeRule { get; }

    // Declare a separate validator for complex rule.
    public ValidationHelper ComplexRule { get; }

    [Reactive] public string Name { get; set; }

    public ReactiveCommand<Unit, Unit> Save { get; }

    // Initialize validation context that manages reactive validations.
    public ValidationContext ValidationContext { get; } = new ValidationContext();
}

View:

<rxui:ReactiveWindow x:Class="Sncf.RealTimeTrain.Views.MainWindow"
                     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                     xmlns:rxui="http://reactiveui.net"
                     xmlns:vms="clr-namespace:Sncf.RealTimeTrain.ViewModels;assembly=Sncf.RealTimeTrain.Shared"
                     d:DataContext="{d:DesignInstance Type=vms:SampleViewModel}"
                     d:DesignHeight="450"
                     d:DesignWidth="800"
                     x:TypeArguments="vms:SampleViewModel"
                     mc:Ignorable="d">
    <StackPanel Margin="20">
        <TextBox x:Name="NameTextBox" Margin="5" />
        <TextBlock x:Name="ErrorsTextBlock" Margin="5" />
    </StackPanel>
</rxui:ReactiveWindow>
public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        this.WhenActivated(disposables =>
        {
            this.Bind(ViewModel, vm => vm.Name, view => view.NameTextBox.Text);
            
            // This works fine
            this.BindValidation(ViewModel, view => view.ErrorsTextBlock.Text);

            // This fails with a NullReferenceException
            this.BindValidation(ViewModel, vm => vm.Name, view => view.ErrorsTextBlock.Text);
        });
    }
}

I'm using the latest stable version of ReactiveUI 9.12.1 and the latest validation version 1.0.3:

    <PackageReference Include="ReactiveUI" Version="9.12.1" />
    <PackageReference Include="ReactiveUI.Fody" Version="9.12.1" />
    <PackageReference Include="ReactiveUI.Validation" Version="1.0.3" />

Also with the one that works, every validation message is appended to each other without a NewLine or anything. How do I customize this? I can open another issue if needed.
Capture

@ThomasPrioul ThomasPrioul added the bug Something isn't working label Mar 28, 2019
@alexmartinezm
Copy link
Contributor

Hi there @ThomasPrioul,

Everything seems fine, so I would need to reproduce it in my machine. The problem is that I don't have a Windows, so I will have to create a virtual machine and then set everything up. I hope to give you some feedback over the weekend.

@alexmartinezm alexmartinezm self-assigned this Mar 29, 2019
@alexmartinezm alexmartinezm added this to To do in Bug Stomping via automation Mar 29, 2019
@alexmartinezm
Copy link
Contributor

Hi again,

The problem is with reflection resolve naming. If you register the validation with "viewModel" instead of "vm" in the lambda expression or by changing the ViewModel validation with the "vm" instead of "viewModel". This workaround works fine.

See the screenshots below:
Not valid
Valid

I will find the solution soon to fix this. And thank you so much for reporting this bug.

@ThomasPrioul
Copy link
Author

Alright, thanks a lot of for investigating this and finding a workaround before the patch!

alexmartinezm added a commit to alexmartinezm/ReactiveUI.Validation that referenced this issue Apr 1, 2019
Bug Stomping automation moved this from To do to Done Apr 1, 2019
@lock lock bot added the outdated label Jun 30, 2019
@lock lock bot locked and limited conversation to collaborators Jun 30, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working outdated
Projects
Bug Stomping
  
Done
Development

No branches or pull requests

2 participants