DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Build a Dynamic Web Form Using Camunda BPMN and DMN
  • Automating a Web Form With Playwright MCP and MySQL MCP
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • Dynamic Web Forms In React For Enterprise Platforms

Trending

  • A Walk-Through of the DZone Article Editor
  • DuckDB for Python Developers
  • Why AI Agents Need a Shared Enterprise Ontology
  • Article Moderation: Your Questions, Answered

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

WPF Validation: How to Validate the Whole Form on the Button Click

In this tutorial, you'll learn how to add a validation field to your application that will be able to tell the user if they've entered incorrect credentials.

By 
Victor Osetskyi
·
Aug. 09, 17 · Tutorial
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
43.9K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

User data warrants verification in just about every application containing these forms. In all likelihood, if you have experience working with WPF application forms, you’ve had to deal with the implementation of validation in some capacity. In spite of the large amount of choices on hand, most of them are developed to function at a “field level.” As such, upon searching for “WPF validation,” you’ll learn how to use IDataErrorInfo. What if the entire form warrants validation, though?

WPF Application Example

For instance, you have an app that has authorization built into it, as well as an authorization window like this one:

Image title

We’ll get the following if the code is expressed:

<Window>
  <Grid>         
    <TextBlock Text="Email: "/>
    <TextBox x:Name="EmailTextBox"/>

    <TextBlock Text="Password: "/>
    <TextBox x:Name="PasswordTextBox"/>

    <Button x:Name="LoginButton">Log in</Button>
  </Grid>
</Window>

You’ll have the login service, of course:

Public class LogInService
  {
    public bool LogIn(string email, string password)
    {
        // In real life you will have some server communication here...but for now:
        return email.Equals("[email protected]") && password.Equals("validPassword");
    }
  }

As suggested, when you perform a query searching for the answer, you may use IDataErrorInfo to disable the Login button (depending on the results of validation). This method will warrant an abundance of interaction with the server. This is why I’ve written this article: a login request can’t be submitted on all password fields or email alterations as it might block your account or IP, among other issues.

The Answer – INotifyDataErrorInfo

Thankfully, we have INotifyDataErrorInfo and IDataErrorInfo, both of which can resolve the problem once implemented, so your model can be viewed as follows:

public class MainWindowViewModel : INotifyDataErrorInfo
  {
    public string Email { get; set; } = "";
    public string Pass { get; set; } = "";

    public IEnumerable GetErrors(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName) || (!HasErrors))
            return null;
        return new List<string>() {"Invalid credentials."};
    }

    public bool HasErrors { get; set; } = false;

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    public bool CheckCredentials()
    {
        HasErrors = !new LogInService().LogIn(Email, Pass);
        if (HasErrors)
        {
            ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs("Email"));
            ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs("Pass"));
        }
        else
        {
            return true;
        }
        return false;
    }
  }

Errors are shown by HasErrors. It’s set to check for credentials once. An actual error is returned by GetErrors. Subscribers are informed about new errors by ErrorsChanged. Also, we supplemented the public helper approach, CheckCredentials, which can be called from the view using our LoginService. Check out this example:

private void LogInButton_Click(object sender, RoutedEventArgs e)
   {
       if (((MainWindowViewModel) DataContext).CheckCredentials())
       {
           Close();
       }   
   }

Bindings will need to be added with ValidatesOnNotifyDataErrors=True in XAML:

<TextBox x:Name="EmailTextBox" Grid.Row="0" Grid.Column="1" Margin="5"
             Text="{Binding Email, ValidatesOnNotifyDataErrors=True}"/>
...
    <TextBox x:Name="PasswordTextBox" Grid.Row="1" Grid.Column="1" Margin="5"
             Text="{Binding Pass, ValidatesOnNotifyDataErrors=True}"/>

Once the app is launched and you enter an incorrect password/email once while clicking the login button, this is what you’ll see:

Image title

Using ValidationRule for Field Level Validation

Now let’s talk about actual field level validation. Think about the modifications we made in the INotifyDataErrorInfo and begin with the ValidationRule method. To see if the email is legitimate, we will use a validation rule of our own. There’s no need to do things from scratch or have your regexps rewritten. I recommend using the following System.Net.Mail.MailAddress:

public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        try
        {
            new MailAddress(value.ToString());
        }
        catch (Exception)
        {
            return new ValidationResult(false, "Please enter a valid email.");
        }
        return new ValidationResult(true, null);
    }

Then we add it to XAML:

<TextBox x:Name="EmailTextBox" Grid.Row="0" Grid.Column="1" Margin="5">
        <TextBox.Text>
            <Binding Path="Email" UpdateSourceTrigger="PropertyChanged">
                <Binding.ValidationRules>
                    <local:EmailValidationRule ValidationStep="RawProposedValue"/>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>

If you have already begun developing your app and it resembles this, then you typed in an incorrect email address:

Image title

It changes as you are typing and will disappear if you enter the valid email.

A Common Example IDataErrorInfo

Most of the data found online on this topic are in reference to IDataErrorInfo. The first step is to implement it into the view mode:

public class MainWindowViewModel : IDataErrorInfo
  {
...

    public string this[string columnName]
    {
        get
        {
            switch (columnName)
            {
                case "Email":
                    if (!IsValidEmail(Email))
                        return "Please enter a valid email.";
                    break;
            }
            return string.Empty;
        }
    }

    public string Error { get; }

    private bool IsValidEmail(string email)
    {
        try
        {
            new MailAddress(email);
        }
        catch (Exception)
        {
            return false;
        }
        return true;
    }
  }

Our indexer inspects the email field when using just the helper approach, IsValidEmail. You must include binding in XAML with ValidatesOnDataErrors=True

And in XAML:

<TextBox x:Name="EmailTextBox" Grid.Row="0" Grid.Column="1" Margin="5"
             Text="{Binding Email, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/>

If you run it once it develops, you’ll have a similar outcome as the one you obtained with the earlier method.

Displaying a Validation Error Text

If you must display a specific message rather than the generic red line around your text box, you can do so by having the ErrorTemplate overridden in XAML, like so:

<Validation.ErrorTemplate>
            <ControlTemplate>
                <StackPanel>
                    <AdornedElementPlaceholder/>
                    <TextBlock Text="{Binding [0].ErrorContent}" Foreground="Red"/>
                </StackPanel>
            </ControlTemplate>
        </Validation.ErrorTemplate>

If you add some space, the form will look like this when you testing it:

Image title

In Closing

WPF provides numerous tools to validate forms. If you would like to leave your thoughts or provide recommendations, please do so in the following comment section. Also, you may visit the original article page and ask your question there to get the help of the professional .NET development company.

Windows Presentation Foundation Form (document)

Published at DZone with permission of Victor Osetskyi. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Build a Dynamic Web Form Using Camunda BPMN and DMN
  • Automating a Web Form With Playwright MCP and MySQL MCP
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • Dynamic Web Forms In React For Enterprise Platforms

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook