Example E4575
Visible to All Users

WPF Data Editors - Create a Registration Form

This example is the application from the Create a Registration Form tutorial. The solution includes projects for each completed tutorial step.

BaseProject

This project is a draft application connected to a database. The project contains two predefined views: MainView with the DXTabControl and RecordsView with the GridControl:

Files to Review

Documentation

Lesson1

This project uses the LayoutControl to arrange data editors within the RegistrationView:

image

Files to Review

Documentation

Lesson2

This project binds data editors to View Model properties:

image

Files to Review

Documentation

Lesson3

This project defines data editor settings (null text, mask, min and max values, popup mode, and data source):

image

Files to Review

Documentation

Lesson4

This project uses ValidationRules to implement input validation and disables the Register button if editors contain validation errors:

image

Files to Review

Documentation

Lesson5

This project uses the IDataErrorInfo interface to obtain validation errors and displays a message box with the registration result:

image

Files to Review

Documentation

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

RegistrationForm.BaseProject/View/MainView.xaml
XAML
<UserControl x:Class="RegistrationForm.View.MainView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" xmlns:ViewModel="clr-namespace:RegistrationForm.ViewModel" xmlns:View="clr-namespace:RegistrationForm.View" mc:Ignorable="d" d:DesignHeight="500" d:DesignWidth="500" DataContext="{dxmvvm:ViewModelSource ViewModel:MainViewModel}"> <dxmvvm:Interaction.Behaviors> <dx:DXMessageBoxService/> </dxmvvm:Interaction.Behaviors> <Grid x:Name="root"> <dx:DXTabControl TabContentCacheMode="CacheAllTabs"> <dx:DXTabControl.View> <dx:TabControlScrollView HeaderLocation="Bottom" HeaderOrientation="Horizontal" ScrollButtonShowMode="Never"/> </dx:DXTabControl.View> <dx:DXTabItem Header="Registration Form"> <View:RegistrationView Width="300" dxmvvm:ViewModelExtensions.ParentViewModel="{Binding ElementName=root, Path=DataContext}"/> </dx:DXTabItem> <dx:DXTabItem Header="Records"> <View:RecordsView dxmvvm:ViewModelExtensions.ParentViewModel="{Binding ElementName=root, Path=DataContext}"/> </dx:DXTabItem> </dx:DXTabControl> </Grid> </UserControl>
RegistrationForm.BaseProject/ViewModel/MainViewModel.cs(vb)
C#
using DevExpress.Mvvm.DataAnnotations; using DevExpress.Mvvm.POCO; namespace RegistrationForm.ViewModel { [POCOViewModel] public class MainViewModel { public static MainViewModel Create() { return ViewModelSource.Create(() => new MainViewModel()); } protected MainViewModel() { } } }
RegistrationForm.BaseProject/View/RecordsView.xaml
XAML
<UserControl x:Class="RegistrationForm.View.RecordsView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid" xmlns:ViewModel="clr-namespace:RegistrationForm.ViewModel" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="400" DataContext="{dxmvvm:ViewModelSource ViewModel:RecordsViewModel}"> <Grid> <dxg:GridControl Name="grid" AutoGenerateColumns="AddNew" ItemsSource="{Binding Employees}"> <dxg:GridControl.View> <dxg:TableView Name="view" ShowGroupPanel="False" AllowEditing="False" AutoWidth="True"/> </dxg:GridControl.View> </dxg:GridControl> </Grid> </UserControl>
RegistrationForm.BaseProject/ViewModel/RecordsViewModel.cs
C#
using DevExpress.Mvvm; using DevExpress.Mvvm.DataAnnotations; using DevExpress.Mvvm.POCO; using RegistrationForm.DataModel; using System.Collections.Generic; namespace RegistrationForm.ViewModel { [POCOViewModel] public class RecordsViewModel { public static RecordsViewModel Create() { return ViewModelSource.Create(() => new RecordsViewModel()); } protected RecordsViewModel() { Messenger.Default.Register<DBEmployeesChangedMessage>(this, OnDBEmployeesChanged); Employees = new List<Employee>(); if(!this.IsInDesignMode()) InitializeEmployees(); } void InitializeEmployees() { Employees = EmployeesModelHelper.GetEmployees(); } void OnDBEmployeesChanged(DBEmployeesChangedMessage message) { InitializeEmployees(); } public virtual List<Employee> Employees { get; set; } } }
RegistrationForm.Lesson1/View/RegistrationView.xaml
XAML
<UserControl x:Class="RegistrationForm.View.RegistrationView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" xmlns:ViewModel="clr-namespace:RegistrationForm.ViewModel" xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="400" DataContext="{dxmvvm:ViewModelSource {x:Type ViewModel:RegistrationViewModel}}"> <UserControl.Resources> <Style x:Key="labelStyle" TargetType="dxlc:LayoutItemLabel"> <Setter Property="FontWeight" Value="Bold"/> </Style> <Style x:Key="itemStyle" TargetType="dxlc:LayoutItem"> <Setter Property="LabelPosition" Value="Top"/> <Setter Property="LabelStyle" Value="{StaticResource labelStyle}"/> </Style> </UserControl.Resources> <Grid> <dxlc:LayoutControl Orientation="Vertical" ItemStyle="{StaticResource itemStyle}" ItemSpace="10"> <dxlc:LayoutGroup ItemSpace="10"> <dxlc:LayoutItem Label="Name"> <dxe:TextEdit /> </dxlc:LayoutItem> <dxe:TextEdit VerticalAlignment="Bottom" /> </dxlc:LayoutGroup> <dxlc:LayoutItem Label="Email"> <dxe:TextEdit /> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Create a password"> <dxe:PasswordBoxEdit /> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Confirm your password"> <dxe:PasswordBoxEdit /> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Birthday"> <dxe:DateEdit /> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Gender"> <dxe:ComboBoxEdit /> </dxlc:LayoutItem> <Button Content="Register" HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="80" /> </dxlc:LayoutControl> </Grid> </UserControl>
RegistrationForm.Lesson2/View/RegistrationView.xaml
XAML
<UserControl x:Class="RegistrationForm.View.RegistrationView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" xmlns:ViewModel="clr-namespace:RegistrationForm.ViewModel" xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="400" DataContext="{dxmvvm:ViewModelSource {x:Type ViewModel:RegistrationViewModel}}"> <UserControl.Resources> <Style x:Key="labelStyle" TargetType="dxlc:LayoutItemLabel"> <Setter Property="FontWeight" Value="Bold"/> </Style> <Style x:Key="itemStyle" TargetType="dxlc:LayoutItem"> <Setter Property="LabelPosition" Value="Top"/> <Setter Property="LabelStyle" Value="{StaticResource labelStyle}"/> </Style> </UserControl.Resources> <Grid> <dxlc:LayoutControl Orientation="Vertical" ItemStyle="{StaticResource itemStyle}" ItemSpace="10"> <dxlc:LayoutGroup ItemSpace="10"> <dxlc:LayoutItem Label="Name"> <dxe:TextEdit EditValue="{Binding FirstName}" /> </dxlc:LayoutItem> <dxe:TextEdit VerticalAlignment="Bottom" EditValue="{Binding LastName}" /> </dxlc:LayoutGroup> <dxlc:LayoutItem Label="Email"> <dxe:TextEdit EditValue="{Binding Email}" /> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Create a password"> <dxe:PasswordBoxEdit EditValue="{Binding Password}" /> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Confirm your password"> <dxe:PasswordBoxEdit EditValue="{Binding ConfirmPassword}" /> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Birthday"> <dxe:DateEdit EditValue="{Binding Birthday}" /> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Gender"> <dxe:ComboBoxEdit EditValue="{Binding Gender}" /> </dxlc:LayoutItem> <Button Content="Register" HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="80" Command="{Binding AddEmployeeCommand}" /> </dxlc:LayoutControl> </Grid> </UserControl>
RegistrationForm.Lesson2/ViewModel/RegistrationViewModel.cs
C#
using DevExpress.Mvvm.DataAnnotations; using DevExpress.Mvvm.POCO; using RegistrationForm.DataModel; using System; namespace RegistrationForm.ViewModel { [POCOViewModel] public class RegistrationViewModel { public static RegistrationViewModel Create() { return ViewModelSource.Create(() => new RegistrationViewModel()); } protected RegistrationViewModel() { if(this.IsInDesignMode()) InitializeInDesignMode(); else InitializeInRuntime(); } void InitializeInDesignMode() { FirstName = "John"; LastName = "Smith"; Email = "John.Smith@JohnSmithMail.com"; Password = "Password"; ConfirmPassword = "Password"; Birthday = new DateTime(1980, 1, 1); Gender = 1; } void InitializeInRuntime() { Birthday = null; Gender = -1; } public virtual string FirstName { get; set; } public virtual string LastName { get; set; } public virtual string Email { get; set; } public virtual string Password { get; set; } public virtual string ConfirmPassword { get; set; } public virtual DateTime? Birthday { get; set; } public virtual int Gender { get; set; } public void AddEmployee() { EmployeesModelHelper.AddNewEmployee(FirstName, LastName, Email, Password, Birthday.Value, Gender); } } }
RegistrationForm.Lesson3/View/RegistrationView.xaml
XAML
<UserControl x:Class="RegistrationForm.View.RegistrationView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" xmlns:ViewModel="clr-namespace:RegistrationForm.ViewModel" xmlns:DataModel="clr-namespace:RegistrationForm.DataModel" xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" xmlns:sys="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="400" DataContext="{dxmvvm:ViewModelSource {x:Type ViewModel:RegistrationViewModel}}"> <UserControl.Resources> <Style x:Key="labelStyle" TargetType="dxlc:LayoutItemLabel"> <Setter Property="FontWeight" Value="Bold"/> </Style> <Style x:Key="itemStyle" TargetType="dxlc:LayoutItem"> <Setter Property="LabelPosition" Value="Top"/> <Setter Property="LabelStyle" Value="{StaticResource labelStyle}"/> </Style> </UserControl.Resources> <Grid> <dxlc:LayoutControl Orientation="Vertical" ItemStyle="{StaticResource itemStyle}" ItemSpace="10"> <dxlc:LayoutGroup ItemSpace="10"> <dxlc:LayoutItem Label="Name"> <dxe:TextEdit EditValue="{Binding FirstName}" NullText="FIRST"/> </dxlc:LayoutItem> <dxe:TextEdit VerticalAlignment="Bottom" EditValue="{Binding LastName}" NullText="LAST"/> </dxlc:LayoutGroup> <dxlc:LayoutItem Label="Email"> <dxe:TextEdit EditValue="{Binding Email}" MaskType="RegEx" Mask="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}" MaskIgnoreBlank="True" InvalidValueBehavior="AllowLeaveEditor" /> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Create a password"> <dxe:PasswordBoxEdit EditValue="{Binding Password}" /> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Confirm your password"> <dxe:PasswordBoxEdit EditValue="{Binding ConfirmPassword}" /> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Birthday"> <dxe:DateEdit EditValue="{Binding Birthday}" InvalidValueBehavior="AllowLeaveEditor" MinValue="{Binding MinBirthday}" MaxValue="{Binding MaxBirthday}"> <dxe:DateEdit.StyleSettings> <dxe:DateEditPickerStyleSettings/> </dxe:DateEdit.StyleSettings> </dxe:DateEdit> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Gender"> <dxe:ComboBoxEdit EditValue="{Binding Gender}" NullText="I am..." ItemsSource="{x:Static Member=DataModel:GenderList.Source}" ValueMember="ID" DisplayMember="Description"> <dxe:ComboBoxEdit.NullValue> <sys:Int32>-1</sys:Int32> </dxe:ComboBoxEdit.NullValue> </dxe:ComboBoxEdit> </dxlc:LayoutItem> <Button Content="Register" HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="80" Command="{Binding AddEmployeeCommand}" /> </dxlc:LayoutControl> </Grid> </UserControl>
RegistrationForm.Lesson3/ViewModel/RegistrationViewModel.cs
C#
using DevExpress.Mvvm.DataAnnotations; using DevExpress.Mvvm.POCO; using RegistrationForm.DataModel; using System; namespace RegistrationForm.ViewModel { [POCOViewModel] public class RegistrationViewModel { public static RegistrationViewModel Create() { return ViewModelSource.Create(() => new RegistrationViewModel()); } protected RegistrationViewModel() { MinBirthday = new DateTime(DateTime.Now.Year - 100, 12, 31); MaxBirthday = new DateTime(DateTime.Now.Year - 1, 12, 31); if(this.IsInDesignMode()) InitializeInDesignMode(); else InitializeInRuntime(); } void InitializeInDesignMode() { FirstName = "John"; LastName = "Smith"; Email = "John.Smith@JohnSmithMail.com"; Password = "Password"; ConfirmPassword = "Password"; Birthday = new DateTime(1980, 1, 1); Gender = 1; } void InitializeInRuntime() { Birthday = null; Gender = -1; } public virtual string FirstName { get; set; } public virtual string LastName { get; set; } public virtual string Email { get; set; } public virtual string Password { get; set; } public virtual string ConfirmPassword { get; set; } public virtual DateTime? Birthday { get; set; } public virtual DateTime MinBirthday { get; set; } public virtual DateTime MaxBirthday { get; set; } public virtual int Gender { get; set; } public void AddEmployee() { EmployeesModelHelper.AddNewEmployee(FirstName, LastName, Email, Password, Birthday.Value, Gender); } } }
RegistrationForm.Lesson4/View/RegistrationView.xaml
XAML
<UserControl x:Class="RegistrationForm.View.RegistrationView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" xmlns:ViewModel="clr-namespace:RegistrationForm.ViewModel" xmlns:DataModel="clr-namespace:RegistrationForm.DataModel" xmlns:Common="clr-namespace:RegistrationForm.Common" xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" xmlns:sys="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="400" DataContext="{dxmvvm:ViewModelSource {x:Type ViewModel:RegistrationViewModel}}"> <UserControl.Resources> <Style x:Key="labelStyle" TargetType="dxlc:LayoutItemLabel"> <Setter Property="FontWeight" Value="Bold"/> </Style> <Style x:Key="itemStyle" TargetType="dxlc:LayoutItem"> <Setter Property="LabelPosition" Value="Top"/> <Setter Property="LabelStyle" Value="{StaticResource labelStyle}"/> </Style> </UserControl.Resources> <Grid> <dxlc:LayoutControl x:Name="container" dxe:ValidationService.IsValidationContainer="True" Orientation="Vertical" ItemStyle="{StaticResource itemStyle}" ItemSpace="10"> <dxlc:LayoutGroup ItemSpace="10"> <dxlc:LayoutItem Label="Name"> <dxe:TextEdit NullText="FIRST" ValidateOnEnterKeyPressed="True" ValidateOnTextInput="False"> <dxe:TextEdit.EditValue> <Binding Path="FirstName" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"> <Binding.ValidationRules> <Common:RequiredValidationRule FieldName="First Name"/> </Binding.ValidationRules> </Binding> </dxe:TextEdit.EditValue> </dxe:TextEdit> </dxlc:LayoutItem> <dxe:TextEdit VerticalAlignment="Bottom" NullText="LAST"> <dxe:TextEdit.EditValue> <Binding Path="LastName" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"> <Binding.ValidationRules> <Common:RequiredValidationRule FieldName="Last Name"/> </Binding.ValidationRules> </Binding> </dxe:TextEdit.EditValue> </dxe:TextEdit> </dxlc:LayoutGroup> <dxlc:LayoutItem Label="Email"> <dxe:TextEdit MaskType="RegEx" Mask="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}" MaskIgnoreBlank="True" InvalidValueBehavior="AllowLeaveEditor"> <dxe:TextEdit.EditValue> <Binding Path="Email" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"> <Binding.ValidationRules> <Common:RequiredValidationRule FieldName="Email"/> </Binding.ValidationRules> </Binding> </dxe:TextEdit.EditValue> </dxe:TextEdit> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Create a password"> <dxe:PasswordBoxEdit> <dxe:PasswordBoxEdit.EditValue> <Binding Path="Password" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"> <Binding.ValidationRules> <Common:RequiredValidationRule FieldName="Password"/> </Binding.ValidationRules> </Binding> </dxe:PasswordBoxEdit.EditValue> </dxe:PasswordBoxEdit> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Confirm your password"> <dxe:PasswordBoxEdit EditValue="{Binding ConfirmPassword}" ValidateOnEnterKeyPressed="True" ValidateOnTextInput="True"/> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Birthday"> <dxe:DateEdit InvalidValueBehavior="AllowLeaveEditor" MinValue="{Binding MinBirthday}" MaxValue="{Binding MaxBirthday}"> <dxe:DateEdit.EditValue> <Binding Path="Birthday" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"> <Binding.ValidationRules> <Common:RequiredValidationRule FieldName="Birthday"/> </Binding.ValidationRules> </Binding> </dxe:DateEdit.EditValue> <dxe:DateEdit.StyleSettings> <dxe:DateEditPickerStyleSettings/> </dxe:DateEdit.StyleSettings> </dxe:DateEdit> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Gender"> <dxe:ComboBoxEdit NullText="I am..." ItemsSource="{x:Static Member=DataModel:GenderList.Source}" ValueMember="ID" DisplayMember="Description"> <dxe:ComboBoxEdit.EditValue> <Binding Path="Gender" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"> <Binding.ValidationRules> <Common:RequiredValidationRule FieldName="Gender"/> </Binding.ValidationRules> </Binding> </dxe:ComboBoxEdit.EditValue> <dxe:ComboBoxEdit.NullValue> <sys:Int32>-1</sys:Int32> </dxe:ComboBoxEdit.NullValue> </dxe:ComboBoxEdit> </dxlc:LayoutItem> <Button Content="Register" HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="80" Command="{Binding AddEmployeeCommand}" IsEnabled="{Binding ElementName=container, Path=(dxe:ValidationService.HasValidationError), Converter={dxmvvm:BooleanNegationConverter}}"/> </dxlc:LayoutControl> </Grid> </UserControl>
RegistrationForm.Lesson4/Common/ValidationRules.cs(vb)
C#
using DevExpress.Mvvm; using System; using System.Globalization; using System.Linq.Expressions; using System.Windows.Controls; namespace RegistrationForm.Common { public class RequiredValidationRule : ValidationRule { public static string GetErrorMessage(string fieldName, object fieldValue, object nullValue = null) { string errorMessage = string.Empty; if(nullValue != null && nullValue.Equals(fieldValue)) errorMessage = string.Format("You cannot leave the {0} field empty.", fieldName); if(fieldValue == null || string.IsNullOrEmpty(fieldValue.ToString())) errorMessage = string.Format("You cannot leave the {0} field empty.", fieldName); return errorMessage; } public static string GetErrorMessage<T>(Expression<Func<T>> expression, object fieldValue, object nullValue = null) { string fieldName = BindableBase.GetPropertyName(expression); return GetErrorMessage(fieldName, fieldValue, nullValue); } public string FieldName { get; set; } public override ValidationResult Validate(object value, CultureInfo cultureInfo) { string error = GetErrorMessage(FieldName, value); if(!string.IsNullOrEmpty(error)) return new ValidationResult(false, error); return ValidationResult.ValidResult; } } }
RegistrationForm.Lesson5/View/RegistrationView.xaml
XAML
<UserControl x:Class="RegistrationForm.View.RegistrationView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" xmlns:ViewModel="clr-namespace:RegistrationForm.ViewModel" xmlns:DataModel="clr-namespace:RegistrationForm.DataModel" xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" xmlns:sys="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="400" DataContext="{dxmvvm:ViewModelSource {x:Type ViewModel:RegistrationViewModel}}"> <UserControl.Resources> <Style x:Key="labelStyle" TargetType="dxlc:LayoutItemLabel"> <Setter Property="FontWeight" Value="Bold"/> </Style> <Style x:Key="itemStyle" TargetType="dxlc:LayoutItem"> <Setter Property="LabelPosition" Value="Top"/> <Setter Property="LabelStyle" Value="{StaticResource labelStyle}"/> </Style> </UserControl.Resources> <Grid> <dxlc:LayoutControl x:Name="container" dxe:ValidationService.IsValidationContainer="True" Orientation="Vertical" ItemStyle="{StaticResource itemStyle}" ItemSpace="10"> <dxlc:LayoutGroup ItemSpace="10"> <dxlc:LayoutItem Label="Name"> <dxe:TextEdit NullText="FIRST" ValidateOnEnterKeyPressed="True" ValidateOnTextInput="False"> <dxe:TextEdit.EditValue> <Binding Path="FirstName" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"/> </dxe:TextEdit.EditValue> </dxe:TextEdit> </dxlc:LayoutItem> <dxe:TextEdit VerticalAlignment="Bottom" NullText="LAST"> <dxe:TextEdit.EditValue> <Binding Path="LastName" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"/> </dxe:TextEdit.EditValue> </dxe:TextEdit> </dxlc:LayoutGroup> <dxlc:LayoutItem Label="Email"> <dxe:TextEdit MaskType="RegEx" Mask="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}" MaskIgnoreBlank="True" InvalidValueBehavior="AllowLeaveEditor"> <dxe:TextEdit.EditValue> <Binding Path="Email" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"/> </dxe:TextEdit.EditValue> </dxe:TextEdit> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Create a password"> <dxe:PasswordBoxEdit> <dxe:PasswordBoxEdit.EditValue> <Binding Path="Password" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"/> </dxe:PasswordBoxEdit.EditValue> </dxe:PasswordBoxEdit> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Confirm your password"> <dxe:PasswordBoxEdit EditValue="{Binding ConfirmPassword, ValidatesOnDataErrors=True}" ValidateOnEnterKeyPressed="True" ValidateOnTextInput="True"/> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Birthday"> <dxe:DateEdit InvalidValueBehavior="AllowLeaveEditor" MinValue="{Binding MinBirthday}" MaxValue="{Binding MaxBirthday}"> <dxe:DateEdit.EditValue> <Binding Path="Birthday" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"/> </dxe:DateEdit.EditValue> <dxe:DateEdit.StyleSettings> <dxe:DateEditPickerStyleSettings/> </dxe:DateEdit.StyleSettings> </dxe:DateEdit> </dxlc:LayoutItem> <dxlc:LayoutItem Label="Gender"> <dxe:ComboBoxEdit NullText="I am..." ItemsSource="{x:Static Member=DataModel:GenderList.Source}" ValueMember="ID" DisplayMember="Description"> <dxe:ComboBoxEdit.EditValue> <Binding Path="Gender" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"/> </dxe:ComboBoxEdit.EditValue> <dxe:ComboBoxEdit.NullValue> <sys:Int32>-1</sys:Int32> </dxe:ComboBoxEdit.NullValue> </dxe:ComboBoxEdit> </dxlc:LayoutItem> <Button Content="Register" HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="80" Command="{Binding AddEmployeeCommand}" IsEnabled="{Binding ElementName=container, Path=(dxe:ValidationService.HasValidationError), Converter={dxmvvm:BooleanNegationConverter}}"/> </dxlc:LayoutControl> </Grid> </UserControl>
RegistrationForm.Lesson5/ViewModel/RegistrationViewModel.cs
C#
using DevExpress.Mvvm; using DevExpress.Mvvm.DataAnnotations; using DevExpress.Mvvm.POCO; using RegistrationForm.DataModel; using System; using System.ComponentModel; using System.Windows; namespace RegistrationForm.ViewModel { [POCOViewModel] public class RegistrationViewModel : IDataErrorInfo { public static RegistrationViewModel Create() { return ViewModelSource.Create(() => new RegistrationViewModel()); } protected RegistrationViewModel() { MinBirthday = new DateTime(DateTime.Now.Year - 100, 12, 31); MaxBirthday = new DateTime(DateTime.Now.Year - 1, 12, 31); if(this.IsInDesignMode()) InitializeInDesignMode(); else InitializeInRuntime(); } void InitializeInDesignMode() { FirstName = "John"; LastName = "Smith"; Email = "John.Smith@JohnSmithMail.com"; Password = "Password"; ConfirmPassword = "Password"; Birthday = new DateTime(1980, 1, 1); Gender = 1; } void InitializeInRuntime() { Birthday = null; Gender = -1; } public virtual string FirstName { get; set; } public virtual string LastName { get; set; } public virtual string Email { get; set; } public virtual string Password { get; set; } public virtual string ConfirmPassword { get; set; } public virtual DateTime? Birthday { get; set; } public virtual DateTime MinBirthday { get; set; } public virtual DateTime MaxBirthday { get; set; } public virtual int Gender { get; set; } public void AddEmployee() { string error = EnableValidationAndGetError(); if(error != null) { OnValidationFailed(error); return; } EmployeesModelHelper.AddNewEmployee(FirstName, LastName, Email, Password, Birthday.Value, Gender); OnValidationSucceeded(); } protected void OnPasswordChanged() { this.RaisePropertyChanged(x => x.ConfirmPassword); } void OnValidationSucceeded() { this.GetService<IMessageBoxService>().Show("Registration succeeded", "Registration Form", MessageBoxButton.OK); } void OnValidationFailed(string error) { this.GetService<IMessageBoxService>().Show("Registration failed. " + error, "Registration Form", MessageBoxButton.OK); } bool allowValidation = false; string EnableValidationAndGetError() { allowValidation = true; string error = ((IDataErrorInfo)this).Error; if(!string.IsNullOrEmpty(error)) { this.RaisePropertiesChanged(); return error; } return null; } string IDataErrorInfo.Error { get { if(!allowValidation) return null; IDataErrorInfo me = (IDataErrorInfo)this; string error = me[BindableBase.GetPropertyName(() => FirstName)] + me[BindableBase.GetPropertyName(() => LastName)] + me[BindableBase.GetPropertyName(() => Email)] + me[BindableBase.GetPropertyName(() => Password)] + me[BindableBase.GetPropertyName(() => ConfirmPassword)] + me[BindableBase.GetPropertyName(() => Birthday)] + me[BindableBase.GetPropertyName(() => Gender)]; if(!string.IsNullOrEmpty(error)) return "Please check inputted data."; return null; } } string IDataErrorInfo.this[string columnName] { get { if(!allowValidation) return null; string firstNameProp = BindableBase.GetPropertyName(() => FirstName); string lastNameProp = BindableBase.GetPropertyName(() => LastName); string emailProp = BindableBase.GetPropertyName(() => Email); string passwordProp = BindableBase.GetPropertyName(() => Password); string confirmPasswordProp = BindableBase.GetPropertyName(() => ConfirmPassword); string birthdayProp = BindableBase.GetPropertyName(() => Birthday); string genderProp = BindableBase.GetPropertyName(() => Gender); if (columnName == firstNameProp) { if (FirstName == null || string.IsNullOrEmpty(FirstName)) return string.Format("You cannot leave the {0} field empty.", firstNameProp); } else if (columnName == lastNameProp) { if (LastName == null || string.IsNullOrEmpty(LastName)) return string.Format("You cannot leave the {0} field empty.", lastNameProp); } else if (columnName == emailProp) { if (Email == null || string.IsNullOrEmpty(Email)) return string.Format("You cannot leave the {0} field empty.", emailProp); } else if (columnName == passwordProp) { if (Password == null || string.IsNullOrEmpty(Password)) return string.Format("You cannot leave the {0} field empty.", passwordProp); } else if (columnName == confirmPasswordProp) { if (!string.IsNullOrEmpty(Password) && Password != ConfirmPassword) return "These passwords do not match. Please try again."; } else if (columnName == birthdayProp) { if (Birthday == null || string.IsNullOrEmpty(Birthday.ToString())) return string.Format("You cannot leave the {0} field empty.", birthdayProp); } else if (columnName == genderProp) { if (Gender == -1) return string.Format("You cannot leave the {0} field empty.", genderProp); } return null; } } } }
RegistrationForm.Lesson5/View/MainView.xaml
XAML
<UserControl x:Class="RegistrationForm.View.MainView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" xmlns:ViewModel="clr-namespace:RegistrationForm.ViewModel" xmlns:View="clr-namespace:RegistrationForm.View" mc:Ignorable="d" d:DesignHeight="500" d:DesignWidth="500" DataContext="{dxmvvm:ViewModelSource ViewModel:MainViewModel}"> <dxmvvm:Interaction.Behaviors> <dx:DXMessageBoxService/> </dxmvvm:Interaction.Behaviors> <Grid x:Name="root"> <dx:DXTabControl TabContentCacheMode="CacheAllTabs"> <dx:DXTabControl.View> <dx:TabControlScrollView HeaderLocation="Bottom" HeaderOrientation="Horizontal" ScrollButtonShowMode="Never"/> </dx:DXTabControl.View> <dx:DXTabItem Header="Registration Form"> <View:RegistrationView Width="300" dxmvvm:ViewModelExtensions.ParentViewModel="{Binding ElementName=root, Path=DataContext}"/> </dx:DXTabItem> <dx:DXTabItem Header="Records"> <View:RecordsView dxmvvm:ViewModelExtensions.ParentViewModel="{Binding ElementName=root, Path=DataContext}"/> </dx:DXTabItem> </dx:DXTabControl> </Grid> </UserControl>

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.