WPF - How can I validate a new instance of an object?

109 Views Asked by At

I have this class

public class Doctor
{
    private string licenseNumber;
    public string LicenseNumber
    {
        get
        {
            return this.licenseNumber;
        }
        set
        {
            if (value.Length > 4)
                throw new MyException("License Number can't be more then 4 digits.\n");
            if (!new Regex("^[0-9]*$").Match(value).Success) // Allow only numbers
                throw new MyException("Only numbers are allowed in a License Number.\n");
            this.licenseNumber = value.PadLeft(4,'0'); // Pad with zeros to 4 digits
        }
    }
    private string name;
    public string Name
    {
        get
        {
            return this.name;
        }
        set
        {
            if (!new Regex("^[a-zA-Z ]*$").Match(value).Success) // Allow only letters and spaces 
                throw new MyException("Only letters and spaces are allowed in a name.\n");
            this.name = value;
        }
    }
    private string phoneNumber;
    public string PhoneNumber
    {
        get
        {
            return this.phoneNumber;
        }
        set
        {
            {
                if (!new Regex("^0[2-9]-[0-9]{7}$").Match(value).Success) // allow only numbers in format 0[2-9]-xxxxxxx
                    throw new MyException("ERROR: only numbers in format 0[2-9]-xxxxxxx are legal\n");
                this.phoneNumber = value;
            }
        }
    }

}

and much more properties inside it. Of course the ctor of this class accepts only form of ctor with values inside, and enter the values to the props. Now, I've created a form, which within the user can add a new Doctor. Thing is - I want to validate the form before the user click on 'Add'. This is a shorted version of my 'add' form in XML:

<Window x:Class="PLForms.AddDoctor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="AddDoctor" Height="431" Width="381" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:my="clr-namespace:BE;assembly=BE" Loaded="Window_Loaded" Background="White" ResizeMode="CanResizeWithGrip" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Margin="12" HorizontalAlignment="Left" VerticalAlignment="Top">
<Window.Resources>
    <CollectionViewSource x:Key="doctorViewSource" d:DesignSource="{d:DesignInstance my:Doctor, CreateList=True}" />
</Window.Resources>
    <Grid Height="367" Name="grid1" Width="296" Margin="12" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="29" />
        </Grid.RowDefinitions>
        <Grid DataContext="{StaticResource doctorViewSource}" HorizontalAlignment="Left" Margin="19,13,0,0" Name="grid2" VerticalAlignment="Top">
            <Label Content="Name:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />
            <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="nameTextBox" Text="{Binding Path=Name, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />
            <Label Content="Phone Number:" Grid.Column="0" Grid.Row="3" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />
            <TextBox Grid.Column="1" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="3" Name="phoneNumberTextBox" Text="{Binding Path=PhoneNumber, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />
        </Grid>
        <Button Content="Add" Name="Add" BorderBrush="#FF612355" Foreground="White" Click="Add_Click" Margin="0,326,0,0" Grid.RowSpan="2">
            <Button.Background>
                <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
                    <GradientStop Color="Black" Offset="0" />
                    <GradientStop Color="#85081DDA" Offset="0.893" />
                </LinearGradientBrush>
            </Button.Background>
        </Button>
    </Grid>

Now, I think that the validation of data will activated only if I set "DataContext" somehow. I've tried to set a sample Doctor object in the form, assign DataContext to the instance of this object, and then - when the user update the data to illegal one - it activate the validation, and red border is marked around the textbox. But I'm looking how to 'activate' validation even if there's no instance of Doctor before - when the user got a blank form, fill it by himself, and only then try to click on 'Add'. My problem is that in this way, I can't attach DataContext property to anything, since I don't have a Doctor instance, and of course I can't create an empty one, because all of the exceptions I created myself... I'll be happy to know what's the logic of Adding data to database, and validate it before, not just in update. T

1

There are 1 best solutions below

2
On

Have you looked at validation attributes? That should make your code cleaner and you don't have to throw exceptions anymore since the user won't be able to add invalid data to the database.