<Window x:Class="BusinessLayerValidation.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPF IDataErrorInfo Sample" Width="350" Height="150"
xmlns:src="clr-namespace:BusinessLayerValidation">
<Window.Resources>
<src:Person x:Key="data"/>
<!--The tool tip for the TextBox to display the validation error message.-->
<Style x:Key="textBoxInError" TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid Name="test">
<Border
BorderBrush="#d99"
BorderThickness="2" x:Name="bd">
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Border>
<Border Name="ErrorImage"
Background="Red" HorizontalAlignment="Right">
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Margin="20">
<TextBlock>Enter your Name:</TextBlock>
<TextBox Style="{StaticResource textBoxInError}">
<TextBox.Text>
<!-- Setting the ValidatesOnDataErrors to true enables to the Binding to check for
errors raised by the IDataErrorInfo implementation.
Alternatively, you can add DataErrorValidationRule to <Binding.ValidationRules/>-->
<Binding Path="Name" Source="{StaticResource data}"
ValidatesOnDataErrors="True"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<!-- Checks for exceptions during the setting of the source property.
Alternatively, set ValidatesOnExceptions to True on the Binding.-->
<ExceptionValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock>Enter your age:</TextBlock>
<TextBox Style="{StaticResource textBoxInError}">
<TextBox.Text>
<!-- Setting the ValidatesOnDataErrors to true enables to the Binding to check for
errors raised by the IDataErrorInfo implementation.
Alternatively, you can add DataErrorValidationRule to <Binding.ValidationRules/>-->
<Binding Path="Age" Source="{StaticResource data}"
ValidatesOnDataErrors="True"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<!-- Checks for exceptions during the setting of the source property.
Alternatively, set ValidatesOnExceptions to True on the Binding.-->
<ExceptionValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace BusinessLayerValidation
{
public class Person : IDataErrorInfo
{
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
public string Error
{
get
{
return null;
}
}
private string name1;
public string Name
{
get { return name1; }
set { name1 = value; }
}
public string this[string name]
{
get
{
string result = null;
if (name == "Age")
{
if (this.age < 0 || this.age > 150)
{
result = "Age must not be less than 0 or greater than 150.";
}
}
if (name == "Name")
{
if (this.name1 == string.Empty || this.name1 == null)
{
result = "Provide Name";
}
}
return result;
}
}
}
}
27/08/13
13/08/13
Insert Update Delete mVVm
Create model folder,
1) public class EmployeeDTO
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime HireDate { get; set; }
public int Title { get; set; }
}
2)
public class GetData
{
public List<EmployeeDTO> employees;
public List<EmployeeDTO> GetEmployees()
{
employees = new List<EmployeeDTO>();
EmployeeDTO employee = new EmployeeDTO();
employee.ID = 1;
employee.FirstName = "Jason";
employee.LastName = "Apergis";
employees.Add(employee);
employee = new EmployeeDTO();
employee.ID = 2;
employee.FirstName = "Ethan";
employee.LastName = "Apergis";
employees.Add(employee);
employee = new EmployeeDTO();
employee.ID = 3;
employee.FirstName = "Caroline";
employee.LastName = "Apergis";
employees.Add(employee);
return employees;
}
private static int count = 10;
public void InsertEmployeeDTO(EmployeeDTO employee)
{
//Code to insert employee
employee.ID = count++;
employees.Add(employee);
}
public void UpdateEmployeeDTO(EmployeeDTO employee)
{
//Code to update employee
}
public void DeleteEmployeeDTO(EmployeeDTO employee)
{
//Code to delete employee
employees.Remove(employee);
}
}
3) Create View Model folder Inside it delete command , insert command, update command, empoyee view model
public class DeleteCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private EmployeeViewModel _evm = null;
public DeleteCommand(EmployeeViewModel evm)
{
_evm = evm;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_evm.Delete();
}
}
public class InsertCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private EmployeeViewModel _evm = null;
public InsertCommand(EmployeeViewModel evm)
{
_evm = evm;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_evm.Insert();
}
}
public class SaveCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private EmployeeViewModel _evm = null;
public SaveCommand(EmployeeViewModel evm)
{
_evm = evm;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_evm.Save();
}
}
ViewModel---------------------------
public class EmployeeViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private GetData _context = null;
private EmployeeDTO _selectedEmployee = null;
public EmployeeViewModel()
{
_context = new GetData();
_context.GetEmployees();
}
public EmployeeDTO SelectedEmployee
{
get
{
return _selectedEmployee;
}
set
{
_selectedEmployee = value;
RaisePropertyChanged("SelectedEmployee");
}
}
public IList<EmployeeDTO> Employees
{
get
{
return _context.employees;
}
}
public ICommand SaveCommand
{
get
{
return new SaveCommand(this);
}
}
public void Save()
{
if (_context.employees != null)
{
RaisePropertyChanged("Employees");
}
}
public ICommand InsertCommand
{
get
{
return new InsertCommand(this);
}
}
public void Insert()
{
EmployeeDTO employee = new EmployeeDTO();
employee.ID = 0;
_context.InsertEmployeeDTO(employee);
RaisePropertyChanged("Employees");
}
public ICommand DeleteCommand
{
get
{
return new DeleteCommand(this);
}
}
public void Delete()
{
_context.employees.Remove(SelectedEmployee);
RaisePropertyChanged("Employees");
}
private void RaisePropertyChanged(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
}
MainWindow Xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" x:Name="employeeview" Background="White">
<DataGrid AutoGenerateColumns="True" Name="grdEmployees"
Height="168" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="400"
ItemsSource="{Binding Employees}"
SelectedItem="{Binding SelectedEmployee, Mode=TwoWay}"/>
<Button Content="Insert" Height="23" HorizontalAlignment="Left" Margin="232,176,0,0"
Name="btnInsert" VerticalAlignment="Top" Width="75"
Command="{Binding InsertCommand}"/>
<Button Content="Delete" Height="23" HorizontalAlignment="Left" Margin="313,176,0,0"
Name="btnDelete" VerticalAlignment="Top" Width="75"
Command="{Binding DeleteCommand}"/>
</Grid>
<Grid Grid.Row="1" x:Name="updateview" Background="White">
<TextBox Height="23" HorizontalAlignment="Left" Margin="12,12,0,0"
Name="txtFirstName" VerticalAlignment="Top" Width="120"
Text="{Binding SelectedEmployee.FirstName, Mode=TwoWay}"/>
<TextBox Height="23" HorizontalAlignment="Left" Margin="138,12,0,0"
Name="txtLastName" VerticalAlignment="Top" Width="120"
Text="{Binding SelectedEmployee.LastName, Mode=TwoWay}"/>
<Button Content="Save" Height="23" HorizontalAlignment="Left"
Margin="264,12,0,0" Name="btnSave" VerticalAlignment="Top"
Width="75" Command="{Binding SaveCommand}"/>
</Grid>
</Grid>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
EmployeeViewModel emv = new EmployeeViewModel();
employeeview.DataContext = emv;
updateview.DataContext = emv;
}
}
1) public class EmployeeDTO
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime HireDate { get; set; }
public int Title { get; set; }
}
2)
public class GetData
{
public List<EmployeeDTO> employees;
public List<EmployeeDTO> GetEmployees()
{
employees = new List<EmployeeDTO>();
EmployeeDTO employee = new EmployeeDTO();
employee.ID = 1;
employee.FirstName = "Jason";
employee.LastName = "Apergis";
employees.Add(employee);
employee = new EmployeeDTO();
employee.ID = 2;
employee.FirstName = "Ethan";
employee.LastName = "Apergis";
employees.Add(employee);
employee = new EmployeeDTO();
employee.ID = 3;
employee.FirstName = "Caroline";
employee.LastName = "Apergis";
employees.Add(employee);
return employees;
}
private static int count = 10;
public void InsertEmployeeDTO(EmployeeDTO employee)
{
//Code to insert employee
employee.ID = count++;
employees.Add(employee);
}
public void UpdateEmployeeDTO(EmployeeDTO employee)
{
//Code to update employee
}
public void DeleteEmployeeDTO(EmployeeDTO employee)
{
//Code to delete employee
employees.Remove(employee);
}
}
3) Create View Model folder Inside it delete command , insert command, update command, empoyee view model
public class DeleteCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private EmployeeViewModel _evm = null;
public DeleteCommand(EmployeeViewModel evm)
{
_evm = evm;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_evm.Delete();
}
}
public class InsertCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private EmployeeViewModel _evm = null;
public InsertCommand(EmployeeViewModel evm)
{
_evm = evm;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_evm.Insert();
}
}
public class SaveCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private EmployeeViewModel _evm = null;
public SaveCommand(EmployeeViewModel evm)
{
_evm = evm;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_evm.Save();
}
}
ViewModel---------------------------
public class EmployeeViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private GetData _context = null;
private EmployeeDTO _selectedEmployee = null;
public EmployeeViewModel()
{
_context = new GetData();
_context.GetEmployees();
}
public EmployeeDTO SelectedEmployee
{
get
{
return _selectedEmployee;
}
set
{
_selectedEmployee = value;
RaisePropertyChanged("SelectedEmployee");
}
}
public IList<EmployeeDTO> Employees
{
get
{
return _context.employees;
}
}
public ICommand SaveCommand
{
get
{
return new SaveCommand(this);
}
}
public void Save()
{
if (_context.employees != null)
{
RaisePropertyChanged("Employees");
}
}
public ICommand InsertCommand
{
get
{
return new InsertCommand(this);
}
}
public void Insert()
{
EmployeeDTO employee = new EmployeeDTO();
employee.ID = 0;
_context.InsertEmployeeDTO(employee);
RaisePropertyChanged("Employees");
}
public ICommand DeleteCommand
{
get
{
return new DeleteCommand(this);
}
}
public void Delete()
{
_context.employees.Remove(SelectedEmployee);
RaisePropertyChanged("Employees");
}
private void RaisePropertyChanged(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
}
MainWindow Xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" x:Name="employeeview" Background="White">
<DataGrid AutoGenerateColumns="True" Name="grdEmployees"
Height="168" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="400"
ItemsSource="{Binding Employees}"
SelectedItem="{Binding SelectedEmployee, Mode=TwoWay}"/>
<Button Content="Insert" Height="23" HorizontalAlignment="Left" Margin="232,176,0,0"
Name="btnInsert" VerticalAlignment="Top" Width="75"
Command="{Binding InsertCommand}"/>
<Button Content="Delete" Height="23" HorizontalAlignment="Left" Margin="313,176,0,0"
Name="btnDelete" VerticalAlignment="Top" Width="75"
Command="{Binding DeleteCommand}"/>
</Grid>
<Grid Grid.Row="1" x:Name="updateview" Background="White">
<TextBox Height="23" HorizontalAlignment="Left" Margin="12,12,0,0"
Name="txtFirstName" VerticalAlignment="Top" Width="120"
Text="{Binding SelectedEmployee.FirstName, Mode=TwoWay}"/>
<TextBox Height="23" HorizontalAlignment="Left" Margin="138,12,0,0"
Name="txtLastName" VerticalAlignment="Top" Width="120"
Text="{Binding SelectedEmployee.LastName, Mode=TwoWay}"/>
<Button Content="Save" Height="23" HorizontalAlignment="Left"
Margin="264,12,0,0" Name="btnSave" VerticalAlignment="Top"
Width="75" Command="{Binding SaveCommand}"/>
</Grid>
</Grid>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
EmployeeViewModel emv = new EmployeeViewModel();
employeeview.DataContext = emv;
updateview.DataContext = emv;
}
}
Input validation
Create folder named Classes
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
2...
public class ViewBase: Window
{
#region " CloseCommandHandler Evnt Handler "
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void CloseCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
Close();
}
#endregion
}
3. Now create model folder and inside it create class
public class Customer : System.ComponentModel.INotifyPropertyChanged, IDataErrorInfo
{
#region " Data Member "
private string strFirstName;
private string strLastName;
private string strEmailAddress;
private string strContactNumber;
#endregion
#region " UserID Property "
/// <summary>
///
/// </summary>
public string UserID { get; set; }
#endregion
#region " FirstName Property "
/// <summary>
///
/// </summary>
public string FirstName
{
get { return strFirstName; }
set
{
strFirstName = value;
RaisePropertyChanged("FirstName");
RaisePropertyChanged("FullName");
}
}
#endregion
#region " FullName Property "
/// <summary>
///
/// </summary>
public string FullName { get { return string.Format("Customer Full Name: {0}, {1}", LastName, FirstName); } }
#endregion
#region " LastName Property "
/// <summary>
///
/// </summary>
public string LastName
{
get { return strLastName; }
set
{
strLastName = value;
RaisePropertyChanged("LastName");
RaisePropertyChanged("FullName");
}
}
#endregion
#region " EmailID Property "
/// <summary>
///
/// </summary>
public string EmailID
{
get { return strEmailAddress; }
set
{
strEmailAddress = value;
RaisePropertyChanged("EmailID");
}
}
#endregion
#region " ContactNumber Property "
/// <summary>
///
/// </summary>
public string ContactNumber
{
get { return strContactNumber; }
set
{
strContactNumber = value;
RaisePropertyChanged("ContactNumber");
}
}
#endregion
#region " DateOfBirth Property "
/// <summary>
///
/// </summary>
public DateTime DateOfBirth { get; set; }
#endregion
#region " INotifyPropertyChanged Members "
#region " PropertyChanged Event "
/// <summary>
///
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region " RaisePropertyChanged Function "
/// <summary>
///
/// </summary>
/// <param name="propertyName"></param>
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
#endregion
#endregion
#region " IDataErrorInfo Members "
#region " Error Property "
/// <summary>
///
/// </summary>
public string Error
{
get { throw new NotImplementedException(); }
}
#endregion
#region " this Property "
/// <summary>
///
/// </summary>
/// <param name="columnName"></param>
/// <returns></returns>
public string this[string columnName]
{
get
{
string strMessage = string.Empty;
ValidateUserInput(ref strMessage, columnName);
return strMessage;
}
}
#endregion
#region " ValidateUserInput Input "
/// <summary>
///
/// </summary>
/// <param name="pstrMessage"></param>
/// <param name="pstrColumnName"></param>
private void ValidateUserInput(ref string pstrMessage, string pstrColumnName)
{
switch (pstrColumnName)
{
case "UserID":
if (string.IsNullOrEmpty(UserID))
pstrMessage = "User ID is required.";
break;
case "FirstName":
if (string.IsNullOrEmpty(FirstName))
pstrMessage = "First name is required.";
else if (string.IsNullOrWhiteSpace(FirstName))
pstrMessage = "Spaces are not allowed in First name. only character are allowed";
else if (FirstName.Length <= 2)
pstrMessage = "First name lenght should be at least 2.";
break;
case "LastName":
if (string.IsNullOrEmpty(LastName))
pstrMessage = "Last name is required.";
else if (string.IsNullOrWhiteSpace(LastName))
pstrMessage = "Spaces are not allowed in Last name. only character are allowed";
break;
case "ContactNumber":
if (string.IsNullOrEmpty(ContactNumber))
pstrMessage = "Contact Number is required";
else if (Regex.IsMatch(ContactNumber, @"^\d+$") == false)
pstrMessage = "Only digits are allowed in Contact Number field.";
break;
case "EmailID":
if (string.IsNullOrEmpty(EmailID))
pstrMessage = "Email ID is required.";
else if (Regex.IsMatch(EmailID, @"^[A-Za-z0-9_\-\.]+@(([A-Za-z0-9\-])+\.)+([A-Za-z\-])+$") == false)
pstrMessage = "Please enter valid email ID.";
break;
}
}
#endregion
#endregion
}
4. Create Customerview model
public class CustomerViewModal
{
#region " ViewTitle Property "
/// <summary>
///
/// </summary>
public string ViewTitle { get; set; }
#endregion
#region " Customers Property "
/// <summary>
///
/// </summary>
public Customer Customers { get; set; }
#endregion
#region " Default Constructor "
/// <summary>
///
/// </summary>
public CustomerViewModal()
{
Customers = new Customer() { ContactNumber = "123456789", DateOfBirth = Convert.ToDateTime("08/08/1981"), EmailID = "myname@hotmail.com", FirstName = "Brett", LastName = "Lee", UserID = "000-ABCD-001" };
ViewTitle = "Customer Form";
}
#endregion
#region " SaveCommand RelayCommand Type "
/// <summary>
///
/// </summary>
RelayCommand saveCommand;
#endregion
#region " SaveCommand Property "
/// <summary>
///
/// </summary>
public ICommand SaveCommand
{
get
{
if (saveCommand == null)
saveCommand = new RelayCommand(CommandExecute, CanCommandExecute);
return saveCommand;
}
}
#endregion
#region " CommandExecute Function "
/// <summary>
///
/// </summary>
/// <param name="parameter"></param>
private void CommandExecute(object parameter)
{
MessageBox.Show(Customers.FullName);
}
#endregion
#region " CanCommandExecute Function "
/// <summary>
///
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
private bool CanCommandExecute(object parameter)
{
// Code here
return true;
}
#endregion
}
5..
Now create main window
<classes:ViewBase
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:classes="clr-namespace:Input_Validation_In_MVVM.Classes"
xmlns:local="clr-namespace:Input_Validation_In_MVVM.ViewModel"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" x:Class="Input_Validation_In_MVVM.MainWindow"
Title="MainWindow" Height="320" Width="410"
AllowsTransparency="True" WindowStyle="None"
Background="Transparent"
WindowStartupLocation="CenterScreen"
>
<classes:ViewBase.CommandBindings>
<CommandBinding Command="ApplicationCommands.Close"
Executed="CloseCommandHandler"/>
</classes:ViewBase.CommandBindings>
<classes:ViewBase.DataContext >
<local:CustomerViewModal/>
</classes:ViewBase.DataContext>
<Grid Background="Transparent" >
<Grid.RowDefinitions >
<RowDefinition Height="30"/>
<RowDefinition />
<RowDefinition Height="40"/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<GroupBox Grid.RowSpan="4" Header="Customer Input Form" Margin="2" FontSize="18.667" Height="310" />
<Grid DataContext="{Binding Customers}" Grid.Row="1">
<Grid.RowDefinitions >
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="75*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding FullName}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="5,0,5,0"/>
<TextBlock Text="User ID :" Grid.Row="1" />
<TextBox Grid.Row="1" Grid.Column="1" Margin="2,1,10,1" Text="{Binding UserID, Mode=TwoWay, ValidatesOnDataErrors=True}" Height="23"/>
<TextBlock Text="Frist Name :" Grid.Row="2" />
<TextBox Grid.Row="2" Grid.Column="1" Margin="2,1,10,1" Text="{Binding FirstName, Mode=TwoWay, ValidatesOnDataErrors=True}" Height="23"/>
<TextBlock Text="Last Name :" Grid.Row="3" />
<TextBox Grid.Row="3" Grid.Column="1" Margin="2,1,10,1" Text="{Binding LastName, Mode=TwoWay, ValidatesOnDataErrors=True}" Height="23"/>
<TextBlock Text="Email Address :" Grid.Row="4" />
<TextBox Grid.Row="4" Grid.Column="1" Margin="2,1,10,1" Text="{Binding EmailID, Mode=TwoWay, ValidatesOnDataErrors=True}" Height="23"/>
<TextBlock Text="Contact No. :" Grid.Row="5" />
<TextBox Grid.Row="5" Grid.Column="1" Margin="2,1,10,1" Text="{Binding ContactNumber, Mode=TwoWay, ValidatesOnDataErrors=True}" Height="23"/>
<TextBlock Text="Date Of Birth :" Grid.Row="6" />
<DatePicker Grid.Column="1" Grid.Row="6" Margin="2,1,10,1" Text="{Binding DateOfBirth, Mode=TwoWay}" Height="23"/>
</Grid>
<Button Content="Save" Grid.Row="2" Grid.Column="1" Width="75" Margin="0,3,90,3" HorizontalAlignment="Right" Command="{Binding SaveCommand}" BorderThickness="2" Height="28"/>
<Button Content="Close" Grid.Row="2" Grid.Column="1" Width="75" Margin="0,3,10,3" HorizontalAlignment="Right" Command="ApplicationCommands.Close" BorderThickness="2" Height="28"/>
</Grid>
</classes:ViewBase>
Now Done
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
2...
public class ViewBase: Window
{
#region " CloseCommandHandler Evnt Handler "
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void CloseCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
Close();
}
#endregion
}
3. Now create model folder and inside it create class
public class Customer : System.ComponentModel.INotifyPropertyChanged, IDataErrorInfo
{
#region " Data Member "
private string strFirstName;
private string strLastName;
private string strEmailAddress;
private string strContactNumber;
#endregion
#region " UserID Property "
/// <summary>
///
/// </summary>
public string UserID { get; set; }
#endregion
#region " FirstName Property "
/// <summary>
///
/// </summary>
public string FirstName
{
get { return strFirstName; }
set
{
strFirstName = value;
RaisePropertyChanged("FirstName");
RaisePropertyChanged("FullName");
}
}
#endregion
#region " FullName Property "
/// <summary>
///
/// </summary>
public string FullName { get { return string.Format("Customer Full Name: {0}, {1}", LastName, FirstName); } }
#endregion
#region " LastName Property "
/// <summary>
///
/// </summary>
public string LastName
{
get { return strLastName; }
set
{
strLastName = value;
RaisePropertyChanged("LastName");
RaisePropertyChanged("FullName");
}
}
#endregion
#region " EmailID Property "
/// <summary>
///
/// </summary>
public string EmailID
{
get { return strEmailAddress; }
set
{
strEmailAddress = value;
RaisePropertyChanged("EmailID");
}
}
#endregion
#region " ContactNumber Property "
/// <summary>
///
/// </summary>
public string ContactNumber
{
get { return strContactNumber; }
set
{
strContactNumber = value;
RaisePropertyChanged("ContactNumber");
}
}
#endregion
#region " DateOfBirth Property "
/// <summary>
///
/// </summary>
public DateTime DateOfBirth { get; set; }
#endregion
#region " INotifyPropertyChanged Members "
#region " PropertyChanged Event "
/// <summary>
///
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region " RaisePropertyChanged Function "
/// <summary>
///
/// </summary>
/// <param name="propertyName"></param>
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
#endregion
#endregion
#region " IDataErrorInfo Members "
#region " Error Property "
/// <summary>
///
/// </summary>
public string Error
{
get { throw new NotImplementedException(); }
}
#endregion
#region " this Property "
/// <summary>
///
/// </summary>
/// <param name="columnName"></param>
/// <returns></returns>
public string this[string columnName]
{
get
{
string strMessage = string.Empty;
ValidateUserInput(ref strMessage, columnName);
return strMessage;
}
}
#endregion
#region " ValidateUserInput Input "
/// <summary>
///
/// </summary>
/// <param name="pstrMessage"></param>
/// <param name="pstrColumnName"></param>
private void ValidateUserInput(ref string pstrMessage, string pstrColumnName)
{
switch (pstrColumnName)
{
case "UserID":
if (string.IsNullOrEmpty(UserID))
pstrMessage = "User ID is required.";
break;
case "FirstName":
if (string.IsNullOrEmpty(FirstName))
pstrMessage = "First name is required.";
else if (string.IsNullOrWhiteSpace(FirstName))
pstrMessage = "Spaces are not allowed in First name. only character are allowed";
else if (FirstName.Length <= 2)
pstrMessage = "First name lenght should be at least 2.";
break;
case "LastName":
if (string.IsNullOrEmpty(LastName))
pstrMessage = "Last name is required.";
else if (string.IsNullOrWhiteSpace(LastName))
pstrMessage = "Spaces are not allowed in Last name. only character are allowed";
break;
case "ContactNumber":
if (string.IsNullOrEmpty(ContactNumber))
pstrMessage = "Contact Number is required";
else if (Regex.IsMatch(ContactNumber, @"^\d+$") == false)
pstrMessage = "Only digits are allowed in Contact Number field.";
break;
case "EmailID":
if (string.IsNullOrEmpty(EmailID))
pstrMessage = "Email ID is required.";
else if (Regex.IsMatch(EmailID, @"^[A-Za-z0-9_\-\.]+@(([A-Za-z0-9\-])+\.)+([A-Za-z\-])+$") == false)
pstrMessage = "Please enter valid email ID.";
break;
}
}
#endregion
#endregion
}
4. Create Customerview model
public class CustomerViewModal
{
#region " ViewTitle Property "
/// <summary>
///
/// </summary>
public string ViewTitle { get; set; }
#endregion
#region " Customers Property "
/// <summary>
///
/// </summary>
public Customer Customers { get; set; }
#endregion
#region " Default Constructor "
/// <summary>
///
/// </summary>
public CustomerViewModal()
{
Customers = new Customer() { ContactNumber = "123456789", DateOfBirth = Convert.ToDateTime("08/08/1981"), EmailID = "myname@hotmail.com", FirstName = "Brett", LastName = "Lee", UserID = "000-ABCD-001" };
ViewTitle = "Customer Form";
}
#endregion
#region " SaveCommand RelayCommand Type "
/// <summary>
///
/// </summary>
RelayCommand saveCommand;
#endregion
#region " SaveCommand Property "
/// <summary>
///
/// </summary>
public ICommand SaveCommand
{
get
{
if (saveCommand == null)
saveCommand = new RelayCommand(CommandExecute, CanCommandExecute);
return saveCommand;
}
}
#endregion
#region " CommandExecute Function "
/// <summary>
///
/// </summary>
/// <param name="parameter"></param>
private void CommandExecute(object parameter)
{
MessageBox.Show(Customers.FullName);
}
#endregion
#region " CanCommandExecute Function "
/// <summary>
///
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
private bool CanCommandExecute(object parameter)
{
// Code here
return true;
}
#endregion
}
5..
Now create main window
<classes:ViewBase
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:classes="clr-namespace:Input_Validation_In_MVVM.Classes"
xmlns:local="clr-namespace:Input_Validation_In_MVVM.ViewModel"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" x:Class="Input_Validation_In_MVVM.MainWindow"
Title="MainWindow" Height="320" Width="410"
AllowsTransparency="True" WindowStyle="None"
Background="Transparent"
WindowStartupLocation="CenterScreen"
>
<classes:ViewBase.CommandBindings>
<CommandBinding Command="ApplicationCommands.Close"
Executed="CloseCommandHandler"/>
</classes:ViewBase.CommandBindings>
<classes:ViewBase.DataContext >
<local:CustomerViewModal/>
</classes:ViewBase.DataContext>
<Grid Background="Transparent" >
<Grid.RowDefinitions >
<RowDefinition Height="30"/>
<RowDefinition />
<RowDefinition Height="40"/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<GroupBox Grid.RowSpan="4" Header="Customer Input Form" Margin="2" FontSize="18.667" Height="310" />
<Grid DataContext="{Binding Customers}" Grid.Row="1">
<Grid.RowDefinitions >
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="75*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding FullName}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="5,0,5,0"/>
<TextBlock Text="User ID :" Grid.Row="1" />
<TextBox Grid.Row="1" Grid.Column="1" Margin="2,1,10,1" Text="{Binding UserID, Mode=TwoWay, ValidatesOnDataErrors=True}" Height="23"/>
<TextBlock Text="Frist Name :" Grid.Row="2" />
<TextBox Grid.Row="2" Grid.Column="1" Margin="2,1,10,1" Text="{Binding FirstName, Mode=TwoWay, ValidatesOnDataErrors=True}" Height="23"/>
<TextBlock Text="Last Name :" Grid.Row="3" />
<TextBox Grid.Row="3" Grid.Column="1" Margin="2,1,10,1" Text="{Binding LastName, Mode=TwoWay, ValidatesOnDataErrors=True}" Height="23"/>
<TextBlock Text="Email Address :" Grid.Row="4" />
<TextBox Grid.Row="4" Grid.Column="1" Margin="2,1,10,1" Text="{Binding EmailID, Mode=TwoWay, ValidatesOnDataErrors=True}" Height="23"/>
<TextBlock Text="Contact No. :" Grid.Row="5" />
<TextBox Grid.Row="5" Grid.Column="1" Margin="2,1,10,1" Text="{Binding ContactNumber, Mode=TwoWay, ValidatesOnDataErrors=True}" Height="23"/>
<TextBlock Text="Date Of Birth :" Grid.Row="6" />
<DatePicker Grid.Column="1" Grid.Row="6" Margin="2,1,10,1" Text="{Binding DateOfBirth, Mode=TwoWay}" Height="23"/>
</Grid>
<Button Content="Save" Grid.Row="2" Grid.Column="1" Width="75" Margin="0,3,90,3" HorizontalAlignment="Right" Command="{Binding SaveCommand}" BorderThickness="2" Height="28"/>
<Button Content="Close" Grid.Row="2" Grid.Column="1" Width="75" Margin="0,3,10,3" HorizontalAlignment="Right" Command="ApplicationCommands.Close" BorderThickness="2" Height="28"/>
</Grid>
</classes:ViewBase>
Now Done
Get Product & Save Product In MVVM
inside helper folder
public abstract class ObservableObject : INotifyPropertyChanged
{
#region Debugging Aides
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG")]
[DebuggerStepThrough]
public virtual void VerifyPropertyName(string propertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
{
string msg = "Invalid property name: " + propertyName;
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
else
Debug.Fail(msg);
}
}
/// <summary>
/// Returns whether an exception is thrown, or if a Debug.Fail() is used
/// when an invalid property name is passed to the VerifyPropertyName method.
/// The default value is false, but subclasses used by unit tests might
/// override this property's getter to return true.
/// </summary>
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
#endregion // Debugging Aides
#region INotifyPropertyChanged Members
/// <summary>
/// Raises the PropertyChange event for the property specified
/// </summary>
/// <param name="propertyName">Property name to update. Is case-sensitive.</param>
public virtual void RaisePropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
OnPropertyChanged(propertyName);
}
/// <summary>
/// Raised when a property on this object has a new value.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected virtual void OnPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
#endregion // INotifyPropertyChanged Members
}
2..
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
/// <summary>
/// Creates a new command that can always execute.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameters)
{
return _canExecute == null ? true : _canExecute(parameters);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameters)
{
_execute(parameters);
}
#endregion // ICommand Members
}
App.Xaml
<Application x:Class="SimpleMVVMExample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ProductView.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
APP.XAML.CS
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow app = new MainWindow();
ProductViewModel context = new ProductViewModel();
app.DataContext = context;
app.Show();
}
}
Main Window File
<Window x:Class="SimpleMVVMExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Simple MVVM Example" Height="350" Width="525">
<Grid>
<ContentControl Content="{Binding }" HorizontalAlignment="Center" Margin="10" />
</Grid>
</Window>
Product Model Class
public class ProductModel : ObservableObject
{
#region Fields
private int _productId;
private string _productName;
private decimal _unitPrice;
#endregion // Fields
#region Properties
public int ProductId
{
get { return _productId; }
set
{
if (value != _productId)
{
_productId = value;
OnPropertyChanged("ProductId");
}
}
}
public string ProductName
{
get { return _productName; }
set
{
if (value != _productName)
{
_productName = value;
OnPropertyChanged("ProductName");
}
}
}
public decimal UnitPrice
{
get { return _unitPrice; }
set
{
if (value != _unitPrice)
{
_unitPrice = value;
OnPropertyChanged("UnitPrice");
}
}
}
#endregion // Properties
}
ProductView Xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SimpleMVVMExample">
<!--
The View can be defined in a UserControl, a DataTemplate, or a combination of the two.
It can exist as it's own file, or it can be simply added to Window.Resources.
My View is a ResourceDictionary that defines DataTemplates. This ResourceDictionary
needs to be added to the application's ResourceDictionaries at runtime, so it is getting
added it in the MainWindow's Window.Resources XAML.
-->
<!-- DataTemplate for Product Model -->
<DataTemplate DataType="{x:Type local:ProductModel}">
<Border BorderBrush="Black" BorderThickness="1" Padding="20">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="ID" VerticalAlignment="Center" Margin="5" />
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding ProductId}" Margin="5" Width="150" />
<TextBlock Grid.Column="0" Grid.Row="1" Text="Name" VerticalAlignment="Center" Margin="5" />
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ProductName}" Margin="5" Width="150" />
<TextBlock Grid.Column="0" Grid.Row="2" Text="Unit Price" VerticalAlignment="Center" Margin="5" />
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding UnitPrice}" Margin="5" Width="150" />
</Grid>
</Border>
</DataTemplate>
<!-- DataTemplate for Product ViewModel -->
<DataTemplate DataType="{x:Type local:ProductViewModel}">
<DockPanel Margin="20">
<DockPanel DockPanel.Dock="Top">
<TextBlock Margin="10,2" DockPanel.Dock="Left" Text="Enter Product Id" VerticalAlignment="Center" />
<TextBox Margin="10,2" Width="50" VerticalAlignment="Center" Text="{Binding Path=ProductId, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="Save Product" DockPanel.Dock="Right" Margin="10,2" VerticalAlignment="Center"
Command="{Binding Path=SaveProductCommand}" Width="100" />
<Button Content="Get Product" DockPanel.Dock="Right" Margin="10,2" VerticalAlignment="Center"
Command="{Binding Path=GetProductCommand}" IsDefault="True" Width="100" />
</DockPanel>
<ContentControl Margin="10" Content="{Binding Path=CurrentProduct}" />
</DockPanel>
</DataTemplate>
</ResourceDictionary>
4... Product View Model
using System.Windows.Input;
namespace SimpleMVVMExample
{
public class ProductViewModel : ObservableObject
{
#region Fields
private int _productId;
private ProductModel _currentProduct;
private ICommand _getProductCommand;
private ICommand _saveProductCommand;
#endregion
#region Public Properties/Commands
public int ProductId
{
get { return _productId; }
set
{
if (value != _productId)
{
_productId = value;
OnPropertyChanged("ProductId");
}
}
}
public ProductModel CurrentProduct
{
get { return _currentProduct; }
set
{
if (value != _currentProduct)
{
_currentProduct = value;
OnPropertyChanged("CurrentProduct");
}
}
}
public ICommand GetProductCommand
{
get
{
if (_getProductCommand == null)
{
_getProductCommand = new RelayCommand(
param => GetProduct(),
param => ProductId > 0
);
}
return _getProductCommand;
}
}
public ICommand SaveProductCommand
{
get
{
if (_saveProductCommand == null)
{
_saveProductCommand = new RelayCommand(
param => SaveProduct(),
param => (CurrentProduct != null)
);
}
return _saveProductCommand;
}
}
#endregion
#region Private Helpers
private void GetProduct()
{
// Usually you'd get your Product from your datastore,
// but for now we'll just return a new object
ProductModel p = new ProductModel();
p.ProductId = ProductId;
p.ProductName = "Test Product";
p.UnitPrice = 10;
CurrentProduct = p;
}
private void SaveProduct()
{
// You would implement your Product save here
}
#endregion
}
}
public abstract class ObservableObject : INotifyPropertyChanged
{
#region Debugging Aides
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG")]
[DebuggerStepThrough]
public virtual void VerifyPropertyName(string propertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
{
string msg = "Invalid property name: " + propertyName;
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
else
Debug.Fail(msg);
}
}
/// <summary>
/// Returns whether an exception is thrown, or if a Debug.Fail() is used
/// when an invalid property name is passed to the VerifyPropertyName method.
/// The default value is false, but subclasses used by unit tests might
/// override this property's getter to return true.
/// </summary>
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
#endregion // Debugging Aides
#region INotifyPropertyChanged Members
/// <summary>
/// Raises the PropertyChange event for the property specified
/// </summary>
/// <param name="propertyName">Property name to update. Is case-sensitive.</param>
public virtual void RaisePropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
OnPropertyChanged(propertyName);
}
/// <summary>
/// Raised when a property on this object has a new value.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected virtual void OnPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
#endregion // INotifyPropertyChanged Members
}
2..
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
/// <summary>
/// Creates a new command that can always execute.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameters)
{
return _canExecute == null ? true : _canExecute(parameters);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameters)
{
_execute(parameters);
}
#endregion // ICommand Members
}
App.Xaml
<Application x:Class="SimpleMVVMExample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ProductView.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
APP.XAML.CS
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow app = new MainWindow();
ProductViewModel context = new ProductViewModel();
app.DataContext = context;
app.Show();
}
}
Main Window File
<Window x:Class="SimpleMVVMExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Simple MVVM Example" Height="350" Width="525">
<Grid>
<ContentControl Content="{Binding }" HorizontalAlignment="Center" Margin="10" />
</Grid>
</Window>
Product Model Class
public class ProductModel : ObservableObject
{
#region Fields
private int _productId;
private string _productName;
private decimal _unitPrice;
#endregion // Fields
#region Properties
public int ProductId
{
get { return _productId; }
set
{
if (value != _productId)
{
_productId = value;
OnPropertyChanged("ProductId");
}
}
}
public string ProductName
{
get { return _productName; }
set
{
if (value != _productName)
{
_productName = value;
OnPropertyChanged("ProductName");
}
}
}
public decimal UnitPrice
{
get { return _unitPrice; }
set
{
if (value != _unitPrice)
{
_unitPrice = value;
OnPropertyChanged("UnitPrice");
}
}
}
#endregion // Properties
}
ProductView Xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SimpleMVVMExample">
<!--
The View can be defined in a UserControl, a DataTemplate, or a combination of the two.
It can exist as it's own file, or it can be simply added to Window.Resources.
My View is a ResourceDictionary that defines DataTemplates. This ResourceDictionary
needs to be added to the application's ResourceDictionaries at runtime, so it is getting
added it in the MainWindow's Window.Resources XAML.
-->
<!-- DataTemplate for Product Model -->
<DataTemplate DataType="{x:Type local:ProductModel}">
<Border BorderBrush="Black" BorderThickness="1" Padding="20">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="ID" VerticalAlignment="Center" Margin="5" />
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding ProductId}" Margin="5" Width="150" />
<TextBlock Grid.Column="0" Grid.Row="1" Text="Name" VerticalAlignment="Center" Margin="5" />
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ProductName}" Margin="5" Width="150" />
<TextBlock Grid.Column="0" Grid.Row="2" Text="Unit Price" VerticalAlignment="Center" Margin="5" />
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding UnitPrice}" Margin="5" Width="150" />
</Grid>
</Border>
</DataTemplate>
<!-- DataTemplate for Product ViewModel -->
<DataTemplate DataType="{x:Type local:ProductViewModel}">
<DockPanel Margin="20">
<DockPanel DockPanel.Dock="Top">
<TextBlock Margin="10,2" DockPanel.Dock="Left" Text="Enter Product Id" VerticalAlignment="Center" />
<TextBox Margin="10,2" Width="50" VerticalAlignment="Center" Text="{Binding Path=ProductId, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="Save Product" DockPanel.Dock="Right" Margin="10,2" VerticalAlignment="Center"
Command="{Binding Path=SaveProductCommand}" Width="100" />
<Button Content="Get Product" DockPanel.Dock="Right" Margin="10,2" VerticalAlignment="Center"
Command="{Binding Path=GetProductCommand}" IsDefault="True" Width="100" />
</DockPanel>
<ContentControl Margin="10" Content="{Binding Path=CurrentProduct}" />
</DockPanel>
</DataTemplate>
</ResourceDictionary>
4... Product View Model
using System.Windows.Input;
namespace SimpleMVVMExample
{
public class ProductViewModel : ObservableObject
{
#region Fields
private int _productId;
private ProductModel _currentProduct;
private ICommand _getProductCommand;
private ICommand _saveProductCommand;
#endregion
#region Public Properties/Commands
public int ProductId
{
get { return _productId; }
set
{
if (value != _productId)
{
_productId = value;
OnPropertyChanged("ProductId");
}
}
}
public ProductModel CurrentProduct
{
get { return _currentProduct; }
set
{
if (value != _currentProduct)
{
_currentProduct = value;
OnPropertyChanged("CurrentProduct");
}
}
}
public ICommand GetProductCommand
{
get
{
if (_getProductCommand == null)
{
_getProductCommand = new RelayCommand(
param => GetProduct(),
param => ProductId > 0
);
}
return _getProductCommand;
}
}
public ICommand SaveProductCommand
{
get
{
if (_saveProductCommand == null)
{
_saveProductCommand = new RelayCommand(
param => SaveProduct(),
param => (CurrentProduct != null)
);
}
return _saveProductCommand;
}
}
#endregion
#region Private Helpers
private void GetProduct()
{
// Usually you'd get your Product from your datastore,
// but for now we'll just return a new object
ProductModel p = new ProductModel();
p.ProductId = ProductId;
p.ProductName = "Test Product";
p.UnitPrice = 10;
CurrentProduct = p;
}
private void SaveProduct()
{
// You would implement your Product save here
}
#endregion
}
}
Add MVVM
Mainwindow file
<Window x:Class="AddressBookWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Command="{Binding add}" Content="Add" Height="23" HorizontalAlignment="Left" Margin="51,108,0,0" Name="btnAdd" VerticalAlignment="Top" Width="75" />
<Button Command="{Binding update}" Content="Update" Height="23" HorizontalAlignment="Left" Margin="151,108,0,0" Name="btnupdate" VerticalAlignment="Top" Width="75" />
<Label Content="Name:" Height="28" HorizontalAlignment="Left" Margin="141,11,0,0" Name="label1" VerticalAlignment="Top" />
<TextBox Text="{Binding Name}" Height="23" HorizontalAlignment="Left" Margin="193,13,0,0" Name="textBox1" VerticalAlignment="Top" Width="181" />
<Label Content="Address:" Height="28" HorizontalAlignment="Left" Margin="141,40,0,0" Name="label2" VerticalAlignment="Top" />
<TextBox Text="{Binding Address}" Height="23" HorizontalAlignment="Left" Margin="193,42,0,0" Name="textBox2" VerticalAlignment="Top" Width="181" />
<Label Content="E-mail:" Height="28" HorizontalAlignment="Left" Margin="141,69,0,0" Name="label3" VerticalAlignment="Top" />
<TextBox Text="{Binding Email}" Height="23" HorizontalAlignment="Left" Margin="193,71,0,0" Name="textBox3" VerticalAlignment="Top" Width="181" />
<DataGrid AutoGenerateColumns="False" Height="213" HorizontalAlignment="Left" Margin="12,154,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="479">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Header="Name" MinWidth="40" Width="100" />
<DataGridTextColumn Binding="{Binding PersonAddress}" Header="Address" Width="230" />
<DataGridTextColumn Binding="{Binding Email}" Header="E-mail" Width="140" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindowViewModel ViewModel;
public MainWindow()
{
InitializeComponent();
ViewModel=new MainWindowViewModel();
this.DataContext = ViewModel;
dataGrid1.ItemsSource = ViewModel.Entries;
}
}
create class
public class AddCommand:ICommand
{
private readonly MainWindowViewModel _vm;
public AddCommand(MainWindowViewModel vm)
{
_vm = vm;
}
public void Execute(object parameter)
{
_vm.Add();
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
then also
public class Address
{
public Address()
{
}
public string Name { get; set; }
public string PersonAddress { get; set; }
public string Email { get; set; }
}
last one view model
public class MainWindowViewModel: DependencyObject
{
public ObservableCollection<Address> Entries=new ObservableCollection<Address>();
public ICommand add { get; set; }
public ICommand update { get; set; }
#region //dependency properties section
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof (string), typeof (MainWindowViewModel), new PropertyMetadata(default(string)));
public string Name
{
get { return (string) GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
public static readonly DependencyProperty AddressProperty =
DependencyProperty.Register("Address", typeof (string), typeof (MainWindowViewModel), new PropertyMetadata(default(string)));
public string Address
{
get { return (string) GetValue(AddressProperty); }
set { SetValue(AddressProperty, value); }
}
public static readonly DependencyProperty EmailProperty =
DependencyProperty.Register("Email", typeof (string), typeof (MainWindowViewModel), new PropertyMetadata(default(string)));
public string Email
{
get { return (string) GetValue(EmailProperty); }
set { SetValue(EmailProperty, value); }
}
#endregion
public MainWindowViewModel()
{
add=new AddCommand(this);
}
public void Add()
{
Entries.Add(new Address(){Email = this.Email,Name = this.Name,PersonAddress = this.Address});
Name = "";
Address = "";
Email = "";
}
}
<Window x:Class="AddressBookWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Command="{Binding add}" Content="Add" Height="23" HorizontalAlignment="Left" Margin="51,108,0,0" Name="btnAdd" VerticalAlignment="Top" Width="75" />
<Button Command="{Binding update}" Content="Update" Height="23" HorizontalAlignment="Left" Margin="151,108,0,0" Name="btnupdate" VerticalAlignment="Top" Width="75" />
<Label Content="Name:" Height="28" HorizontalAlignment="Left" Margin="141,11,0,0" Name="label1" VerticalAlignment="Top" />
<TextBox Text="{Binding Name}" Height="23" HorizontalAlignment="Left" Margin="193,13,0,0" Name="textBox1" VerticalAlignment="Top" Width="181" />
<Label Content="Address:" Height="28" HorizontalAlignment="Left" Margin="141,40,0,0" Name="label2" VerticalAlignment="Top" />
<TextBox Text="{Binding Address}" Height="23" HorizontalAlignment="Left" Margin="193,42,0,0" Name="textBox2" VerticalAlignment="Top" Width="181" />
<Label Content="E-mail:" Height="28" HorizontalAlignment="Left" Margin="141,69,0,0" Name="label3" VerticalAlignment="Top" />
<TextBox Text="{Binding Email}" Height="23" HorizontalAlignment="Left" Margin="193,71,0,0" Name="textBox3" VerticalAlignment="Top" Width="181" />
<DataGrid AutoGenerateColumns="False" Height="213" HorizontalAlignment="Left" Margin="12,154,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="479">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Header="Name" MinWidth="40" Width="100" />
<DataGridTextColumn Binding="{Binding PersonAddress}" Header="Address" Width="230" />
<DataGridTextColumn Binding="{Binding Email}" Header="E-mail" Width="140" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindowViewModel ViewModel;
public MainWindow()
{
InitializeComponent();
ViewModel=new MainWindowViewModel();
this.DataContext = ViewModel;
dataGrid1.ItemsSource = ViewModel.Entries;
}
}
create class
public class AddCommand:ICommand
{
private readonly MainWindowViewModel _vm;
public AddCommand(MainWindowViewModel vm)
{
_vm = vm;
}
public void Execute(object parameter)
{
_vm.Add();
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
then also
public class Address
{
public Address()
{
}
public string Name { get; set; }
public string PersonAddress { get; set; }
public string Email { get; set; }
}
last one view model
public class MainWindowViewModel: DependencyObject
{
public ObservableCollection<Address> Entries=new ObservableCollection<Address>();
public ICommand add { get; set; }
public ICommand update { get; set; }
#region //dependency properties section
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof (string), typeof (MainWindowViewModel), new PropertyMetadata(default(string)));
public string Name
{
get { return (string) GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
public static readonly DependencyProperty AddressProperty =
DependencyProperty.Register("Address", typeof (string), typeof (MainWindowViewModel), new PropertyMetadata(default(string)));
public string Address
{
get { return (string) GetValue(AddressProperty); }
set { SetValue(AddressProperty, value); }
}
public static readonly DependencyProperty EmailProperty =
DependencyProperty.Register("Email", typeof (string), typeof (MainWindowViewModel), new PropertyMetadata(default(string)));
public string Email
{
get { return (string) GetValue(EmailProperty); }
set { SetValue(EmailProperty, value); }
}
#endregion
public MainWindowViewModel()
{
add=new AddCommand(this);
}
public void Add()
{
Entries.Add(new Address(){Email = this.Email,Name = this.Name,PersonAddress = this.Address});
Name = "";
Address = "";
Email = "";
}
}
Validation In MVVM
First Create Model Inside ValidationMVVM Project
namespace Models
{
using System;
using System.ComponentModel;
class Model : IDataErrorInfo, INotifyPropertyChanged
{
private string customerName;
public string CustomerName
{
get
{
return customerName;
}
set
{
customerName = value;
NotifyPropertyChanged("CustomerName");
}
}
private int customerAge;
public int CustomerAge
{
get
{
return customerAge;
}
set
{
customerAge = value;
NotifyPropertyChanged("CustomerAge");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises the PropertyChanged event for a property.
/// </summary>
/// <param name="propertyName">The name of the property that has changed.</param>
protected void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
#region IDataErrorInfo Members
string IDataErrorInfo.Error
{
get
{
return null;
}
}
string IDataErrorInfo.this[string propertyName]
{
get
{
return GetValidationError(propertyName);
}
}
#endregion
#region Validation
static readonly string[] ValidatedProperties =
{
"CustomerName",
"CustomerAge"
};
public bool IsValid
{
get
{
foreach (string property in ValidatedProperties)
if (GetValidationError(property) != null)
return false;
return true;
}
}
string GetValidationError(String propertyName)
{
string error = null;
switch (propertyName)
{
case "CustomerName":
error = ValidateCustomerName();
break;
case "CustomerAge":
error = ValidateCustomerAge();
break;
default :
error = null;
break;
}
return error;
}
private string ValidateCustomerName()
{
if (String.IsNullOrWhiteSpace(CustomerName))
{
return "Customer name cannot be empty.";
}
return null;
}
private string ValidateCustomerAge()
{
if (CustomerAge < 18)
{
return "Customer Age above 18.";
}
return null;
}
#endregion
}
}
Now time to create View
<Window x:Class="Mvvm.Session03.IDataErrorInfo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Mvvm.Session03.IDataErrorInfo.ViewModels"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:ViewModel x:Key="mainviewModel"/>
</Window.Resources>
<StackPanel DataContext="{StaticResource mainviewModel}" Margin="10">
<TextBox Name="CustomerName"
Text="{Binding Model.CustomerName, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
Validation.ValidationAdornerSite="{Binding ElementName=AdornerSite}"/>
<Label Name="AdornerSite"
FontWeight="Bold"
Foreground="Red"
Content="{Binding ElementName=CustomerName, Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
<TextBox Name="CustomerAge"
Text="{Binding Model.CustomerAge,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}"
Validation.ValidationAdornerSite="{Binding ElementName=AdornerSiteAge}"/>
<Label Name="AdornerSiteAge"
FontWeight="Bold"
Foreground="Red"
Content="{Binding ElementName=CustomerAge, Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</StackPanel>
</Window>
check for glue between model and view
that is viewmodel
namespace ViewModels
{
using System;
using System.ComponentModel;
using Models;
class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
Model = new Model()
{
CustomerName = "Raju",
CustomerAge = 20
};
}
public Model Model
{
get;
set;
}
#region INotifyPropertyChanged Members
/// <summary>
/// Occurs when a property that supports change notification has changed.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises the PropertyChanged event for a property.
/// </summary>
/// <param name="propertyName">The name of the property that has changed.</param>
protected void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}.
namespace Models
{
using System;
using System.ComponentModel;
class Model : IDataErrorInfo, INotifyPropertyChanged
{
private string customerName;
public string CustomerName
{
get
{
return customerName;
}
set
{
customerName = value;
NotifyPropertyChanged("CustomerName");
}
}
private int customerAge;
public int CustomerAge
{
get
{
return customerAge;
}
set
{
customerAge = value;
NotifyPropertyChanged("CustomerAge");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises the PropertyChanged event for a property.
/// </summary>
/// <param name="propertyName">The name of the property that has changed.</param>
protected void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
#region IDataErrorInfo Members
string IDataErrorInfo.Error
{
get
{
return null;
}
}
string IDataErrorInfo.this[string propertyName]
{
get
{
return GetValidationError(propertyName);
}
}
#endregion
#region Validation
static readonly string[] ValidatedProperties =
{
"CustomerName",
"CustomerAge"
};
public bool IsValid
{
get
{
foreach (string property in ValidatedProperties)
if (GetValidationError(property) != null)
return false;
return true;
}
}
string GetValidationError(String propertyName)
{
string error = null;
switch (propertyName)
{
case "CustomerName":
error = ValidateCustomerName();
break;
case "CustomerAge":
error = ValidateCustomerAge();
break;
default :
error = null;
break;
}
return error;
}
private string ValidateCustomerName()
{
if (String.IsNullOrWhiteSpace(CustomerName))
{
return "Customer name cannot be empty.";
}
return null;
}
private string ValidateCustomerAge()
{
if (CustomerAge < 18)
{
return "Customer Age above 18.";
}
return null;
}
#endregion
}
}
Now time to create View
<Window x:Class="Mvvm.Session03.IDataErrorInfo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Mvvm.Session03.IDataErrorInfo.ViewModels"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:ViewModel x:Key="mainviewModel"/>
</Window.Resources>
<StackPanel DataContext="{StaticResource mainviewModel}" Margin="10">
<TextBox Name="CustomerName"
Text="{Binding Model.CustomerName, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
Validation.ValidationAdornerSite="{Binding ElementName=AdornerSite}"/>
<Label Name="AdornerSite"
FontWeight="Bold"
Foreground="Red"
Content="{Binding ElementName=CustomerName, Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
<TextBox Name="CustomerAge"
Text="{Binding Model.CustomerAge,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}"
Validation.ValidationAdornerSite="{Binding ElementName=AdornerSiteAge}"/>
<Label Name="AdornerSiteAge"
FontWeight="Bold"
Foreground="Red"
Content="{Binding ElementName=CustomerAge, Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</StackPanel>
</Window>
check for glue between model and view
that is viewmodel
namespace ViewModels
{
using System;
using System.ComponentModel;
using Models;
class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
Model = new Model()
{
CustomerName = "Raju",
CustomerAge = 20
};
}
public Model Model
{
get;
set;
}
#region INotifyPropertyChanged Members
/// <summary>
/// Occurs when a property that supports change notification has changed.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises the PropertyChanged event for a property.
/// </summary>
/// <param name="propertyName">The name of the property that has changed.</param>
protected void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}.
12/03/13
WPF restart application
I have tried
below code after submitting the data but application gets crashed while
restarting the application.
if (Restart (Condition))
{
System.Windows.Application.Current.Shutdown();
Process MyProcess = new Process();
MyProcess.StartInfo.FileName = Application.ResourceAssembly.Location;
MyProcess.Start();
return;
}
Application.Current.Exit += new ExitEventHandler(Current_Exit);
Application.Current.Shutdown();
void Current_Exit(object sender, ExitEventArgs e)
{
Process.Start(Application.ResourceAssembly.Location);
}
Subscribe to:
Comments (Atom)