Search code examples
validationdata-bindinguwpuwp-xamltemplate10

I dont understand how to call Validation logic with Template 10 Validation


I've been trying to reproduce the simplest validation logic ever possible with template 10 validation, but I Just dont get it.

I have created my Model like the wiki at the example at github:

public class User : ValidatableModelBase
{
    //public User()
    //{
    //    FirstName = string.Empty;
    //    LastName = string.Empty;
    //    Validator = i =>
    //    {
    //        var u = i as User;
    //        if (string.IsNullOrEmpty(u.FirstName))
    //            u.Properties[nameof(u.FirstName)].Errors.Add("The first name is required");
    //        else if (u.FirstName.Length <= 3)
    //            u.Properties[nameof(u.FirstName)].Errors.Add("First Name must be greater than 3 chars.");

    //        if (string.IsNullOrEmpty(u.LastName))
    //            u.Properties[nameof(u.LastName)].Errors.Add("The last name is required");
    //        else if (u.LastName.Length <= 3)
    //            u.Properties[nameof(u.LastName)].Errors.Add("Last Name must be greater than 3 chars.");
    //    };
    //}

    public int Id { get; set; }
    public string FirstName
    {
        get
        {
            return Read<string>();
        }
        set
        {
            Write(value);
        }
    }
    public string LastName
    {
        get
        {
            return Read<string>();
        }
        set
        {
            Write(value);
        }
    }
    public override string ToString() => $"{FirstName} {LastName}";
}

as you can see I've even created a constructor to initialize my Object, I commented out because I wanted to initialize the values at my ViewModel Constructor.

Then my view model is this:

public class MainPageViewModel : ViewModelBase
{
    public MainPageViewModel()
    {
        User = new User
        {
            FirstName = string.Empty,
            LastName = string.Empty,
            Validator = i =>
            {
                var u = i as User;
                if (string.IsNullOrEmpty(u.FirstName))
                    u.Properties[nameof(u.FirstName)].Errors.Add("The first name is required");
                else if (u.FirstName.Length <= 3)
                    u.Properties[nameof(u.FirstName)].Errors.Add("First Name must be greater than 3 chars.");

                if (string.IsNullOrEmpty(u.LastName))
                    u.Properties[nameof(u.LastName)].Errors.Add("The last name is required");
                else if (u.LastName.Length <= 3)
                    u.Properties[nameof(u.LastName)].Errors.Add("Last Name must be greater than 3 chars.");
            },
        };
    }

    private User _User;

    public User User
    {
        get { return _User; }
        set { _User = value; }
    }


    public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState)
    {
        User.Validate();
        await Task.CompletedTask;
    }

    public override async Task OnNavigatingFromAsync(NavigatingEventArgs args)
    {
        args.Cancel = false;
        await Task.CompletedTask;
    }

    public void GotoSettings() =>
        NavigationService.Navigate(typeof(Views.SettingsPage), 0);

    public void GotoPrivacy() =>
        NavigationService.Navigate(typeof(Views.SettingsPage), 1);

    public void GotoAbout() =>
        NavigationService.Navigate(typeof(Views.SettingsPage), 2);

}

Now at my view all I have is this:

<Page x:Class="ValidationSample.Views.MainPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:Behaviors="using:Template10.Behaviors"
  xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
  xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
  xmlns:controls="using:Template10.Controls"
  xmlns:validate="using:Template10.Controls.Validation"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:local="using:ValidationSample.Views"
  xmlns:m="using:ValidationSample.Models"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:vm="using:ValidationSample.ViewModels" mc:Ignorable="d">

<Page.DataContext>
    <vm:MainPageViewModel x:Name="ViewModel" />
</Page.DataContext>

<RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="AdaptiveVisualStateGroup">
            <VisualState x:Name="VisualStateNarrow">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="{StaticResource NarrowMinWidth}" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <!--  TODO: change properties for narrow view  -->
                    <!--<Setter Target="stateTextBox.Text" Value="Narrow Visual State" />-->
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="VisualStateNormal">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="{StaticResource NormalMinWidth}" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <!--  TODO: change properties for normal view  -->
                    <!--<Setter Target="stateTextBox.Text" Value="Normal Visual State" />-->
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="VisualStateWide">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="{StaticResource WideMinWidth}" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <!--  TODO: change properties for wide view  -->
                    <!--<Setter Target="stateTextBox.Text" Value="Wide Visual State" />-->
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <controls:PageHeader x:Name="pageHeader" RelativePanel.AlignLeftWithPanel="True"
                         RelativePanel.AlignRightWithPanel="True"
                         RelativePanel.AlignTopWithPanel="True" Text="Main Page">

        <!--  secondary commands  -->
        <controls:PageHeader.SecondaryCommands>
            <AppBarButton Click="{x:Bind ViewModel.GotoSettings}" Label="Settings" />
            <AppBarButton Click="{x:Bind ViewModel.GotoPrivacy}" Label="Privacy" />
            <AppBarButton Click="{x:Bind ViewModel.GotoAbout}" Label="About" />
        </controls:PageHeader.SecondaryCommands>

    </controls:PageHeader>

    <validate:ControlWrapper PropertyName="FirstName"                                  
                             RelativePanel.AlignLeftWithPanel="True"
                             RelativePanel.Below="pageHeader">
        <TextBox Width="300"
                 Margin="12,0,0,0"
                 Header="First Name"
                 Text="{Binding FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    </validate:ControlWrapper>

</RelativePanel>

As fas as I know I have the model with the ValidatableModelBase logic Applied, I do have the Validate:wrapper applied to the view, I've set the validator at the VM ctor or I could set it at model ctor.

My problem is where do i make the Calling logic??? Because I havent been able to trigger the UpdateSourceTrigger of my FirstName field.

What am i doing wrong??

To be more honest I dont know where to place the Validate method, because at the sample at github the validate method is call everytime you open the modal dialog window, but that is when you are navigating to that window and its field everytime they changed they are being validated, but in my case nothing happens, why?? Hopefully someone can help me out, since I'm new at template 10 and also at UWP.


Solution

  • Damn, I was so damn tired but my mistake was so god damn simple I forgot to set the DataContext at the Parent Panel, In this case I should had add DataContext ={Binding Model} this at XAML within the relative panel or any other Panel.

    I felt so noob to have made this question.