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
- MainView.xaml (VB: MainView.xaml)
- MainViewModel.cs (VB: MainViewModel.vb)
- RecordsView.xaml (VB: RecordsView.xaml)
- RecordsViewModel.cs (VB: RecordsViewModel.cs)
Documentation
Lesson1
This project uses the LayoutControl to arrange data editors within the RegistrationView:
Files to Review
Documentation
Lesson2
This project binds data editors to View Model properties:
Files to Review
- RegistrationView.xaml (VB: RegistrationView.xaml)
- RegistrationViewModel.cs (VB: RegistrationViewModel.cs)
Documentation
Lesson3
This project defines data editor settings (null text, mask, min and max values, popup mode, and data source):
Files to Review
- RegistrationView.xaml (VB: RegistrationView.xaml)
- RegistrationViewModel.cs (VB: RegistrationViewModel.cs)
Documentation
Lesson4
This project uses ValidationRules to implement input validation and disables the Register button if editors contain validation errors:
Files to Review
Documentation
Lesson5
This project uses the IDataErrorInfo interface to obtain validation errors and displays a message box with the registration result:
Files to Review
- RegistrationView.xaml (VB: RegistrationView.xaml)
- RegistrationViewModel.cs (VB: RegistrationViewModel.vb)
- MainView.xaml (VB: MainView.xaml)
Documentation
Does this example address your development requirements/objectives?
(you will be redirected to DevExpress.com to submit your response)
Example Code
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>
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>
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; }
}
}
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>
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>
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);
}
}
}
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>
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);
}
}
}
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>
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;
}
}
}
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>
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;
}
}
}
}
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>