changeset 96:188f8b366e87

Unit test project correctly setup as normal class library DLL.
author stevenhollidge <stevenhollidge@hotmail.com>
date Sat, 05 May 2012 13:29:56 +0100
parents 64e9903703a3
children 1adc1ae981ea
files SilverlightValidation/Libs/Microsoft.Silverlight.Testing.dll SilverlightValidation/Libs/Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll SilverlightValidation/Libs/NUnit.Silverlight.Compatibility.dll SilverlightValidation/Libs/NUnit.Silverlight.Framework.dll SilverlightValidation/Libs/NUnit.Silverlight.Metadata.dll SilverlightValidation/SilverlightValidation.PL/Commands/RelayCommand.cs SilverlightValidation/SilverlightValidation.PL/Data/Factory.cs SilverlightValidation/SilverlightValidation.PL/Diagrams/Overview.cd SilverlightValidation/SilverlightValidation.PL/Interfaces/ICloneable.cs SilverlightValidation/SilverlightValidation.PL/Interfaces/IUserModel.cs SilverlightValidation/SilverlightValidation.PL/Messages/UserViewResponseMessage.cs SilverlightValidation/SilverlightValidation.PL/Models/UserModel.cs SilverlightValidation/SilverlightValidation.PL/Properties/AssemblyInfo.cs SilverlightValidation/SilverlightValidation.PL/SilverlightValidation.PL.csproj SilverlightValidation/SilverlightValidation.PL/Validators/UserModelValidator.cs SilverlightValidation/SilverlightValidation.PL/ViewModels/UserListViewModel.cs SilverlightValidation/SilverlightValidation.PL/ViewModels/UserViewModel.cs SilverlightValidation/SilverlightValidation.PL/ViewModels/ViewModelBase.cs SilverlightValidation/SilverlightValidation.Tests/Properties/AppManifest.xml SilverlightValidation/SilverlightValidation.Tests/Properties/AssemblyInfo.cs SilverlightValidation/SilverlightValidation.Tests/SilverlightValidation.Tests.csproj SilverlightValidation/SilverlightValidation.Tests/ViewModels/UserListViewModel.cs SilverlightValidation/SilverlightValidation.Tests/ViewModels/UserListViewModelTests.cs SilverlightValidation/SilverlightValidation.Tests/ViewModels/UserViewModel.cs SilverlightValidation/SilverlightValidation.Tests/ViewModels/UserViewModelTests.cs SilverlightValidation/SilverlightValidation.Tests/packages.config SilverlightValidation/SilverlightValidation.sln SilverlightValidation/SilverlightValidation/Commands/RelayCommand.cs SilverlightValidation/SilverlightValidation/Data/Factory.cs SilverlightValidation/SilverlightValidation/Diagrams/Overview.cd SilverlightValidation/SilverlightValidation/Interfaces/ICloneable.cs SilverlightValidation/SilverlightValidation/Interfaces/IUserModel.cs SilverlightValidation/SilverlightValidation/Messages/UserViewResponseMessage.cs SilverlightValidation/SilverlightValidation/Models/UserModel.cs SilverlightValidation/SilverlightValidation/SilverlightValidation.csproj SilverlightValidation/SilverlightValidation/Validators/UserModelValidator.cs SilverlightValidation/SilverlightValidation/ViewModels/UserListViewModel.cs SilverlightValidation/SilverlightValidation/ViewModels/UserViewModel.cs SilverlightValidation/SilverlightValidation/ViewModels/ViewModelBase.cs SilverlightValidation/SilverlightValidation/Views/UserListView.xaml.cs
diffstat 40 files changed, 790 insertions(+), 735 deletions(-) [+]
line wrap: on
line diff
Binary file SilverlightValidation/Libs/Microsoft.Silverlight.Testing.dll has changed
Binary file SilverlightValidation/Libs/Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll has changed
Binary file SilverlightValidation/Libs/NUnit.Silverlight.Compatibility.dll has changed
Binary file SilverlightValidation/Libs/NUnit.Silverlight.Framework.dll has changed
Binary file SilverlightValidation/Libs/NUnit.Silverlight.Metadata.dll has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/Commands/RelayCommand.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,40 @@
+using System;
+using System.Windows.Input;
+
+namespace SilverlightValidation.Commands
+{
+    public class RelayCommand : ICommand
+    {
+        public event EventHandler CanExecuteChanged = delegate { };
+
+        readonly Action<object> _execute;
+        readonly Predicate<object> _canExecute;
+
+        public RelayCommand(Action<object> execute,
+                            Predicate<object> canExecute = null)
+        {
+            if (execute == null) throw new ArgumentNullException("execute");
+
+            _execute = execute;
+            _canExecute = canExecute;
+        }
+
+
+        public void UpdateCanExecuteCommand()
+        {
+            CanExecuteChanged(this, new EventArgs());
+        }
+
+
+        public bool CanExecute(object parameter)
+        {
+            return _canExecute == null || _canExecute(parameter);
+        }
+
+
+        public void Execute(object parameter)
+        {
+            _execute(parameter);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/Data/Factory.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using SilverlightValidation.Models;
+
+namespace SilverlightValidation.Data
+{
+    public class Factory
+    {
+        public static IList<UserModel> CreateUserModels()
+        {
+            return new List<UserModel>(5)
+            {
+                new UserModel() { Username = "StevenH", Password = "Password1", Email = "steven@hotmail.com", DateOfBirth = new DateTime(1977, 09, 01), Description = ""},
+                new UserModel() { Username = "RichardJ", Password = "12N456a", Email = "dicky@gmail.com", DateOfBirth = new DateTime(1983, 03, 13), Description = "Loves .Net!"},
+                new UserModel() { Username = "BobbyP", Password = "pa33Word", Email = "bob@yahoo.co.uk", DateOfBirth = new DateTime(1992, 08, 30), Description = ""},
+                new UserModel() { Username = "DavidM", Password = "poIu789", Email = "daveyboy@marsh.com", DateOfBirth = new DateTime(1965, 06, 21), Description = "Java fan boy"},
+                new UserModel() { Username = "JessieJ", Password = "jlkJh567", Email = "jj@apple.co.uk", DateOfBirth = new DateTime(1990, 10, 15), Description = ""}
+            };
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/Diagrams/Overview.cd	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1">
+  <Class Name="SilverlightValidation.Models.UserModel">
+    <Position X="2.5" Y="1.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAACAgAAAAAQAAAAAAAAAQAEACAAAAAAAAABA=</HashCode>
+      <FileName>Models\UserModel.cs</FileName>
+    </TypeIdentifier>
+    <Lollipop Position="0.2" />
+  </Class>
+  <Class Name="SilverlightValidation.Validators.UserModelValidator" Collapsed="true">
+    <Position X="2" Y="7.75" Width="2" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAA=</HashCode>
+      <FileName>Validators\UserModelValidator.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="SilverlightValidation.ViewModels.UserListViewModel">
+    <Position X="6.25" Y="5.5" Width="2.75" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAECAAAAAAAAAAAAABAYABEACAAAAAA=</HashCode>
+      <FileName>ViewModels\UserListViewModel.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Class Name="SilverlightValidation.ViewModels.UserViewModel">
+    <Position X="4.25" Y="1.75" Width="1.75" />
+    <TypeIdentifier>
+      <HashCode>UAAAoIAADCIgAAAAMYAACAAAAAAQABAKQEAAAAAgIAA=</HashCode>
+      <FileName>ViewModels\UserViewModel.cs</FileName>
+    </TypeIdentifier>
+    <Lollipop Position="0.2" />
+  </Class>
+  <Class Name="SilverlightValidation.ViewModels.ViewModelBase">
+    <Position X="6.25" Y="1.75" Width="2.75" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAACAABQAAABAAAAAgAAgAAAAACIAAAAAAARAAA=</HashCode>
+      <FileName>ViewModels\ViewModelBase.cs</FileName>
+    </TypeIdentifier>
+    <Lollipop Position="0.2" />
+  </Class>
+  <Class Name="SilverlightValidation.Messages.UserViewResponseMessage">
+    <Position X="9.25" Y="5" Width="2.25" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAA=</HashCode>
+      <FileName>Messages\UserViewResponseMessage.cs</FileName>
+    </TypeIdentifier>
+  </Class>
+  <Interface Name="SilverlightValidation.Interfaces.ICloneable&lt;T&gt;">
+    <Position X="2.5" Y="4.5" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA=</HashCode>
+      <FileName>Interfaces\ICloneable.cs</FileName>
+    </TypeIdentifier>
+  </Interface>
+  <Interface Name="SilverlightValidation.Interfaces.IUserModel">
+    <Position X="2.5" Y="5.75" Width="1.5" />
+    <TypeIdentifier>
+      <HashCode>AAAAAAAAACAgAAAAAQAAAAAAAAAQAAACAAAAAAAAAAA=</HashCode>
+      <FileName>Interfaces\IUserModel.cs</FileName>
+    </TypeIdentifier>
+  </Interface>
+  <Font Name="Segoe UI" Size="9" />
+</ClassDiagram>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/Interfaces/ICloneable.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,7 @@
+namespace SilverlightValidation.Interfaces
+{
+  public interface ICloneable<T>
+  {
+    T Clone();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/Interfaces/IUserModel.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,12 @@
+using System;
+namespace SilverlightValidation.Interfaces
+{
+  public interface IUserModel
+  {
+    string Username { get; set; }
+    string Email { get; set; }
+    string Password { get; set; }
+    DateTime? DateOfBirth { get; set; }
+    string Description { get; set; }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/Messages/UserViewResponseMessage.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,10 @@
+using GalaSoft.MvvmLight.Messaging;
+using SilverlightValidation.ViewModels;
+
+namespace SilverlightValidation.Messages
+{
+    public class UserViewResponseMessage : MessageBase
+    {
+        public UserViewModel UserViewModel { get; set; }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/Models/UserModel.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,25 @@
+using System;
+using System.ComponentModel;
+using SilverlightValidation.Interfaces;
+
+namespace SilverlightValidation.Models
+{
+    public class UserModel : IUserModel, ICloneable<UserModel>
+    {
+        public string Username { get; set; }
+        public string Email { get; set; }
+        public string Password { get; set; }
+        public DateTime? DateOfBirth { get; set; }
+        public string Description { get; set; }
+
+        public static UserModel Create()
+        {
+            return new UserModel() { Username = "", Email = "", Password = "", DateOfBirth = null, Description = "" };
+        }
+
+        public UserModel Clone()
+        {
+            return (UserModel) this.MemberwiseClone(); 
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/Properties/AssemblyInfo.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SilverlightValidation.PL")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SilverlightValidation.PL")]
+[assembly: AssemblyCopyright("Copyright ©  2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f669b434-6d0f-48d5-917b-00c92d4ccfee")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/SilverlightValidation.PL.csproj	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{13B5F568-F402-4A2A-9A23-0FDF0B5564E3}</ProjectGuid>
+    <ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SilverlightValidation.PL</RootNamespace>
+    <AssemblyName>SilverlightValidation.PL</AssemblyName>
+    <TargetFrameworkIdentifier>Silverlight</TargetFrameworkIdentifier>
+    <TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
+    <SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
+    <SilverlightApplication>false</SilverlightApplication>
+    <ValidateXaml>true</ValidateXaml>
+    <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
+  </PropertyGroup>
+  <!-- This property group is only here to support building this project using the 
+       MSBuild 3.5 toolset. In order to work correctly with this older toolset, it needs 
+       to set the TargetFrameworkVersion to v3.5 -->
+  <PropertyGroup Condition="'$(MSBuildToolsVersion)' == '3.5'">
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>Bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;TRACE;SILVERLIGHT</DefineConstants>
+    <NoStdLib>true</NoStdLib>
+    <NoConfig>true</NoConfig>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>Bin\Release</OutputPath>
+    <DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
+    <NoStdLib>true</NoStdLib>
+    <NoConfig>true</NoConfig>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="FluentValidation">
+      <HintPath>..\Libs\FluentValidation.dll</HintPath>
+    </Reference>
+    <Reference Include="GalaSoft.MvvmLight.SL5, Version=4.0.21.32885, Culture=neutral, PublicKeyToken=c114982fcf1a3a2e, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Libs\GalaSoft.MvvmLight.SL5.dll</HintPath>
+    </Reference>
+    <Reference Include="mscorlib" />
+    <Reference Include="System.Windows" />
+    <Reference Include="system" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Windows.Controls, Version=5.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\Libs\System.Windows.Controls.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Windows.Controls.Navigation, Version=5.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\Libs\System.Windows.Controls.Navigation.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Commands\RelayCommand.cs" />
+    <Compile Include="Data\Factory.cs" />
+    <Compile Include="Interfaces\ICloneable.cs" />
+    <Compile Include="Interfaces\IUserModel.cs" />
+    <Compile Include="Messages\UserViewResponseMessage.cs" />
+    <Compile Include="Models\UserModel.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Validators\UserModelValidator.cs" />
+    <Compile Include="ViewModels\UserListViewModel.cs" />
+    <Compile Include="ViewModels\UserViewModel.cs" />
+    <Compile Include="ViewModels\ViewModelBase.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Diagrams\Overview.cd" />
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.CSharp.targets" />
+  <ProjectExtensions>
+    <VisualStudio>
+      <FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
+        <SilverlightProjectProperties />
+      </FlavorProperties>
+    </VisualStudio>
+  </ProjectExtensions>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/Validators/UserModelValidator.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,36 @@
+using System;
+using FluentValidation;
+using SilverlightValidation.Interfaces;
+
+namespace SilverlightValidation.Validators
+{
+    public class UserModelValidator : AbstractValidator<IUserModel>
+    {
+        public UserModelValidator()
+        {
+            RuleFor(x => x.Username)
+                .Length(3, 8)
+                .WithMessage("Must be between 3-8 characters.");
+
+            RuleFor(x => x.Password)
+                .Matches(@"^\w*(?=\w*\d)(?=\w*[a-z])(?=\w*[A-Z])\w*$")
+                .WithMessage("Must contain lower, upper and numeric chars.");
+
+            RuleFor(x => x.Email)
+                .EmailAddress()
+                .WithMessage("A valid email address is required.");
+
+            RuleFor(x => x.DateOfBirth)
+                .Must(BeAValidDateOfBirth)
+                .WithMessage("Must be within 100 years of today.");
+        }
+
+        private bool BeAValidDateOfBirth(DateTime? dateOfBirth)
+        {
+            if (dateOfBirth == null) return false;
+            if (dateOfBirth.Value > DateTime.Today || dateOfBirth < DateTime.Today.AddYears(-100))
+                return false;
+            return true;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/ViewModels/UserListViewModel.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,65 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Windows.Controls;
+using System.Windows.Input;
+using SilverlightValidation.Commands;
+using SilverlightValidation.Models;
+using SilverlightValidation.Validators;
+using GalaSoft.MvvmLight.Messaging;
+using SilverlightValidation.Messages;
+
+namespace SilverlightValidation.ViewModels
+{
+    public class UserListViewModel
+    {
+        private ChildWindow _window;
+
+        public UserListViewModel(ChildWindow window, IList<UserModel> models, UserModelValidator validator)
+        {
+            _window = window;
+
+            Data = new ObservableCollection<UserViewModel>();
+
+            foreach (var model in models)
+                Data.Add(new UserViewModel(model, validator));
+
+            AddCommand = new RelayCommand(AddCommandExecute);
+            DeleteCommand = new RelayCommand(DeleteCommandExecute);
+
+            Messenger.Default.Register<UserViewResponseMessage>(this, UserViewResponseMessageReceived);
+        }
+
+        private void UserViewResponseMessageReceived(UserViewResponseMessage userViewResponseMessage)
+        {
+            if (userViewResponseMessage.UserViewModel != null)
+                Data.Add(userViewResponseMessage.UserViewModel);
+            _window.Close();
+        }
+
+        #region Properties
+
+        public ObservableCollection<UserViewModel> Data { get; set; }
+
+        public UserViewModel SelectedItem { get; set; }
+
+        #endregion
+
+        #region Commands
+
+        public ICommand AddCommand { get; set; }
+        public ICommand DeleteCommand { get; set; }
+
+        private void AddCommandExecute(object obj)
+        {
+            _window.Show();
+        }
+
+        private void DeleteCommandExecute(object obj)
+        {
+            if (SelectedItem!=null)
+                Data.Remove(SelectedItem);
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/ViewModels/UserViewModel.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,223 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows;
+using System.Windows.Input;
+using FluentValidation;
+using SilverlightValidation.Interfaces;
+using SilverlightValidation.Validators;
+using SilverlightValidation.Models;
+using SilverlightValidation.Commands;
+using GalaSoft.MvvmLight.Messaging;
+using SilverlightValidation.Messages;
+
+namespace SilverlightValidation.ViewModels
+{
+    public class UserViewModel : ViewModelBase, IUserModel, IEditableObject
+    {
+        #region Fields
+
+        private readonly UserModelValidator _validator;
+        private UserModel _data;
+        private UserModel _backup;
+
+        #endregion
+
+        #region Constructor
+
+        public UserViewModel(UserModel model, UserModelValidator validator)
+        {
+            _validator = validator;
+            _data = model;
+            _backup = model.Clone();
+
+            OkCommand = new RelayCommand(OkCommandExecute);
+            CancelCommand = new RelayCommand(CancelCommandExecute);
+        }
+
+        #endregion
+
+        #region Methods
+
+        private void SetProperties(IUserModel source)
+        {
+            _data.Username = source.Username;
+            _data.Password = source.Password;
+            _data.Email = source.Email;
+            _data.DateOfBirth = source.DateOfBirth;
+            _data.Description = source.Description;
+        }
+
+        #endregion
+
+        #region Properties
+
+        private const string UsernameProperty = "Username";
+        public string Username
+        {
+            get { return _data.Username; }
+            set
+            {
+                if (_data.Username != value)
+                {
+                    _data.Username = value;
+                    RaisePropertyChanged(UsernameProperty);
+                    IsChanged = true;
+                }
+
+                ClearError(UsernameProperty);
+                var validationResult = _validator.Validate(this, UsernameProperty);
+                if (!validationResult.IsValid)
+                    validationResult.Errors.ToList().ForEach(x => SetError(UsernameProperty, x.ErrorMessage));
+            }
+        }
+
+        private const string PasswordProperty = "Password";
+        public string Password
+        {
+            get { return _data.Password; }
+            set
+            {
+                if (_data.Password != value)
+                {
+                    _data.Password = value;
+                    RaisePropertyChanged(PasswordProperty);
+                    IsChanged = true;
+                }
+
+                ClearError(PasswordProperty);
+                var validationResult = _validator.Validate(this, PasswordProperty);
+                if (!validationResult.IsValid)
+                    validationResult.Errors.ToList().ForEach(x => SetError(PasswordProperty, x.ErrorMessage));
+            }
+        }
+
+        private const string EmailProperty = "Email";
+        public string Email
+        {
+            get { return _data.Email; }
+            set
+            {
+                if (_data.Email != value)
+                {
+                    _data.Email = value;
+                    RaisePropertyChanged(EmailProperty);
+                    IsChanged = true;
+                }
+
+                ClearError(EmailProperty);
+                var validationResult = _validator.Validate(this, EmailProperty);
+                if (!validationResult.IsValid)
+                    validationResult.Errors.ToList().ForEach(x => SetError(EmailProperty, x.ErrorMessage));
+            }
+        }
+
+        private const string DateOfBirthProperty = "DateOfBirth";
+        public DateTime? DateOfBirth
+        {
+            get { return _data.DateOfBirth; }
+            set
+            {
+                if (_data.DateOfBirth != value)
+                {
+                    _data.DateOfBirth = value;
+                    RaisePropertyChanged(DateOfBirthProperty);
+                    IsChanged = true;
+                }
+
+                ClearError(DateOfBirthProperty);
+                var validationResult = _validator.Validate(this, DateOfBirthProperty);
+                if (!validationResult.IsValid)
+                    validationResult.Errors.ToList().ForEach(x => SetError(DateOfBirthProperty, x.ErrorMessage));
+            }
+        }
+
+        private const string DescriptionProperty = "Description";
+        public string Description
+        {
+            get { return _data.Description; }
+            set
+            {
+                if (_data.Description != value)
+                {
+                    _data.Description = value;
+                    RaisePropertyChanged(DescriptionProperty);
+                    IsChanged = true;
+                }
+
+                ClearError(DescriptionProperty);
+                var validationResult = _validator.Validate(this, DescriptionProperty);
+                if (!validationResult.IsValid)
+                    validationResult.Errors.ToList().ForEach(x => SetError(DescriptionProperty, x.ErrorMessage));
+            }
+        }
+
+        #endregion
+
+        #region Commands
+
+        public ICommand OkCommand { get; set; }
+        public ICommand CancelCommand { get; set; }
+
+        private void OkCommandExecute(object obj)
+        {
+            RefreshToViewErrors();
+
+            if (IsChanged && !HasErrors)
+            {
+                // save here
+                Messenger.Default.Send<UserViewResponseMessage>(
+                    new UserViewResponseMessage() { UserViewModel = this });
+            }
+        }
+
+        // in case user hasn't touched the form
+        private void RefreshToViewErrors()
+        {
+            Username = _data.Username;
+            Password = _data.Password;
+            Email = _data.Email;
+            DateOfBirth = _data.DateOfBirth;
+        }
+
+        private void CancelCommandExecute(object obj)
+        {
+            Messenger.Default.Send<UserViewResponseMessage>(
+                new UserViewResponseMessage() { UserViewModel = null });
+        }
+        
+        #endregion
+
+        private void ResetFormData()
+        {
+            SetProperties(_backup);
+            ClearAllErrors();
+            IsChanged = false;
+        }
+
+        public bool IsChanged { get; private set; }
+
+        #region IEditableObject for datagrid
+
+        private bool inEdit;
+        public void BeginEdit()
+        {
+            if (inEdit) return;
+            inEdit = true;
+        }
+
+        public void CancelEdit()
+        {
+            if (!inEdit) return;
+            inEdit = false;
+            ResetFormData();
+        }
+
+        public void EndEdit()
+        {
+            if (!inEdit) return;
+        }
+
+        #endregion
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.PL/ViewModels/ViewModelBase.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,73 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+
+namespace SilverlightValidation.ViewModels
+{
+    public class ViewModelBase : INotifyPropertyChanged, INotifyDataErrorInfo
+    {
+        #region INotifyPropertyChanged method plus event
+
+        public event PropertyChangedEventHandler PropertyChanged = delegate { };
+
+        protected void RaisePropertyChanged(string propertyName)
+        {
+            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+        }
+
+        #endregion
+
+        #region INotifyDataErrorInfo methods and helpers
+
+        private readonly Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>();
+
+        public void SetError(string propertyName, string errorMessage)
+        {
+            if (!_errors.ContainsKey(propertyName))
+                _errors.Add(propertyName, new List<string> { errorMessage });
+
+            RaiseErrorsChanged(propertyName);
+        }
+
+        protected void ClearError(string propertyName)
+        {
+            if (_errors.ContainsKey(propertyName))
+            {
+                _errors.Remove(propertyName);
+                RaiseErrorsChanged(propertyName);
+            }
+        }
+
+        protected void ClearAllErrors()
+        {
+            var errors = _errors.Select(error => error.Key).ToList();
+
+            foreach (var propertyName in errors)
+                ClearError(propertyName);
+        }
+
+        public void RaiseErrorsChanged(string propertyName)
+        {
+            ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
+        }
+
+        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged = delegate { };
+
+        public IEnumerable GetErrors(string propertyName)
+        {
+            if (propertyName == null) return null;
+            return _errors.ContainsKey(propertyName)
+                    ? _errors[propertyName]
+                    : null;
+        }
+
+        public bool HasErrors
+        {
+            get { return _errors.Count > 0; }
+        }
+
+        #endregion
+    }
+}
--- a/SilverlightValidation/SilverlightValidation.Tests/Properties/AppManifest.xml	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
-        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
->
-    <Deployment.Parts>
-    </Deployment.Parts>
-    
-</Deployment>
--- a/SilverlightValidation/SilverlightValidation.Tests/Properties/AssemblyInfo.cs	Sat May 05 11:07:41 2012 +0100
+++ b/SilverlightValidation/SilverlightValidation.Tests/Properties/AssemblyInfo.cs	Sat May 05 13:29:56 2012 +0100
@@ -1,6 +1,4 @@
-// Copyright ©  2012
-
-using System.Reflection;
+using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
@@ -22,7 +20,7 @@
 [assembly: ComVisible(false)]
 
 // The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("1196b633-7f87-485e-bd47-f3d2943a59e4")]
+[assembly: Guid("843ea0ec-635f-4592-b3e6-5893be73bc5e")]
 
 // Version information for an assembly consists of the following four values:
 //
@@ -31,7 +29,8 @@
 //      Build Number
 //      Revision
 //
-// You can specify all the values or you can default the Revision and Build Numbers 
+// You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
 [assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
\ No newline at end of file
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- a/SilverlightValidation/SilverlightValidation.Tests/SilverlightValidation.Tests.csproj	Sat May 05 11:07:41 2012 +0100
+++ b/SilverlightValidation/SilverlightValidation.Tests/SilverlightValidation.Tests.csproj	Sat May 05 13:29:56 2012 +0100
@@ -3,124 +3,59 @@
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>9.0.30729</ProductVersion>
+    <ProductVersion>8.0.30703</ProductVersion>
     <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{12AE7560-AD64-4635-8A6B-772256FF0EDD}</ProjectGuid>
-    <ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+    <ProjectGuid>{02CCF8C7-1311-453F-BF82-3564AD9E7B8C}</ProjectGuid>
     <OutputType>Library</OutputType>
     <AppDesignerFolder>Properties</AppDesignerFolder>
     <RootNamespace>SilverlightValidation.Tests</RootNamespace>
     <AssemblyName>SilverlightValidation.Tests</AssemblyName>
-    <TargetFrameworkIdentifier>Silverlight</TargetFrameworkIdentifier>
-    <TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
-    <SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
-    <SilverlightApplication>true</SilverlightApplication>
-    <SupportedCultures />
-    <XapOutputs>true</XapOutputs>
-    <GenerateSilverlightManifest>true</GenerateSilverlightManifest>
-    <XapFilename>SilverlightValidation.Tests.xap</XapFilename>
-    <SilverlightManifestTemplate>Properties\AppManifest.xml</SilverlightManifestTemplate>
-    <SilverlightAppEntry>SilverlightValidation.Tests.App</SilverlightAppEntry>
-    <TestPageFileName>TestPage.html</TestPageFileName>
-    <CreateTestPage>true</CreateTestPage>
-    <ValidateXaml>true</ValidateXaml>
-    <EnableOutOfBrowser>false</EnableOutOfBrowser>
-    <OutOfBrowserSettingsFile>Properties\OutOfBrowserSettings.xml</OutOfBrowserSettingsFile>
-    <UsePlatformExtensions>false</UsePlatformExtensions>
-    <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
-    <LinkedServerProject />
-  </PropertyGroup>
-  <!--
-  //
-  // Silverlight Code Coverage Instrumentation
-  // List any libraries or assemblies that you would like to instrument during
-  // a code coverage pass. An example, for ClassLibrary1, is provided, and
-  // commented out below as a starting point:
-  //
-  -->
-  <!--
-  <ItemGroup>
-    <InstrumentSilverlightAssemblies Include="SilverlightClassLibrary1">
-      <Visible>false</Visible>
-    </InstrumentSilverlightAssemblies>
-  </ItemGroup>
-  -->
-  <!-- This property group is only here to support building this project using the 
-       MSBuild 3.5 toolset. In order to work correctly with this older toolset, it needs 
-       to set the TargetFrameworkVersion to v3.5 -->
-  <PropertyGroup Condition="'$(MSBuildToolsVersion)' == '3.5'">
-    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
-    <OutputPath>Bin\Debug</OutputPath>
-    <DefineConstants>DEBUG;TRACE;SILVERLIGHT</DefineConstants>
-    <NoStdLib>true</NoStdLib>
-    <NoConfig>true</NoConfig>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
-    <OutputPath>Bin\Release</OutputPath>
-    <DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
-    <NoStdLib>true</NoStdLib>
-    <NoConfig>true</NoConfig>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="Microsoft.Silverlight.Testing">
-      <HintPath>..\Libs\Microsoft.Silverlight.Testing.dll</HintPath>
-    </Reference>
-    <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight">
-      <HintPath>..\Libs\Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll</HintPath>
-    </Reference>
-    <Reference Include="NUnit.Silverlight.Compatibility">
-      <HintPath>..\Libs\NUnit.Silverlight.Compatibility.dll</HintPath>
+    <Reference Include="nunit.framework, Version=2.6.0.12051, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnit.2.6.0.12054\lib\nunit.framework.dll</HintPath>
     </Reference>
-    <Reference Include="NUnit.Silverlight.Framework">
-      <HintPath>..\Libs\NUnit.Silverlight.Framework.dll</HintPath>
-    </Reference>
-    <Reference Include="NUnit.Silverlight.Metadata">
-      <HintPath>..\Libs\NUnit.Silverlight.Metadata.dll</HintPath>
-    </Reference>
-    <Reference Include="System.Windows" />
-    <Reference Include="mscorlib" />
-    <Reference Include="system" />
+    <Reference Include="System" />
     <Reference Include="System.Core" />
-    <Reference Include="System.Net" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
     <Reference Include="System.Xml" />
-    <Reference Include="System.Windows.Browser" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ViewModels\UserListViewModelTests.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="ViewModels\UserListViewModel.cs" />
-    <Compile Include="ViewModels\UserViewModel.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="Properties\AppManifest.xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\SilverlightValidation\SilverlightValidation.csproj">
-      <Project>{0C1CC1FC-915A-4428-8952-CDC79EABC3F4}</Project>
-      <Name>SilverlightValidation</Name>
-    </ProjectReference>
+    <Compile Include="ViewModels\UserViewModelTests.cs" />
   </ItemGroup>
   <ItemGroup>
-    <Folder Include="Validators\" />
+    <None Include="packages.config" />
   </ItemGroup>
-  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.CSharp.targets" />
-  <Import Condition="$(SilverlightVersion)=='v3.0'" Project="$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SilverlightToolkit\Tools\v3.0)Microsoft.Silverlight.Toolkit.Build.targets" />
-  <Import Condition="$(SilverlightVersion)=='v4.0'" Project="$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SilverlightToolkit\Tools\v4.0)Microsoft.Silverlight.Toolkit.Build.targets" />
-  <ProjectExtensions>
-    <VisualStudio>
-      <FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
-        <SilverlightProjectProperties />
-      </FlavorProperties>
-    </VisualStudio>
-  </ProjectExtensions>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
 </Project>
\ No newline at end of file
--- a/SilverlightValidation/SilverlightValidation.Tests/ViewModels/UserListViewModel.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-
-using NUnit.Framework;
-
-namespace SilverlightValidation.Tests.ViewModels
-{
-    [TestFixture]
-    public class UserListViewModelTests
-    {
-        [Test]
-        public void Given_When_Then()
-        {
-            Assert.True(true);
-        }
-    }
-}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.Tests/ViewModels/UserListViewModelTests.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,15 @@
+using System;
+using NUnit.Framework;
+
+namespace SilverlightValidation.Tests.ViewModels
+{
+    [TestFixture]
+    class UserListViewModelTests
+    {
+        [Test]
+        public void Given_When_Then()
+        {
+            Assert.True(true);
+        }
+    }
+}
--- a/SilverlightValidation/SilverlightValidation.Tests/ViewModels/UserViewModel.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-
-using NUnit.Framework;
-
-namespace SilverlightValidation.Tests.ViewModels
-{
-    [TestFixture]
-    public class UserViewModelTests
-    {
-        [Test]
-        public void Given_When_Then()
-        {
-            Assert.True(true);
-        }
-    }
-}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.Tests/ViewModels/UserViewModelTests.cs	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,14 @@
+using NUnit.Framework;
+
+namespace SilverlightValidation.Tests.ViewModels
+{
+    [TestFixture]
+    class UserViewModelTests
+    {
+        [Test]
+        public void Given_When_Then()
+        {
+            Assert.True(true);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SilverlightValidation/SilverlightValidation.Tests/packages.config	Sat May 05 13:29:56 2012 +0100
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="NUnit" version="2.6.0.12054" />
+</packages>
\ No newline at end of file
--- a/SilverlightValidation/SilverlightValidation.sln	Sat May 05 11:07:41 2012 +0100
+++ b/SilverlightValidation/SilverlightValidation.sln	Sat May 05 13:29:56 2012 +0100
@@ -5,7 +5,9 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SilverlightValidation.Web", "SilverlightValidation.Web\SilverlightValidation.Web.csproj", "{E65C6757-932B-4D01-9A8A-6D02F8FAA25A}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SilverlightValidation.Tests", "SilverlightValidation.Tests\SilverlightValidation.Tests.csproj", "{12AE7560-AD64-4635-8A6B-772256FF0EDD}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SilverlightValidation.PL", "SilverlightValidation.PL\SilverlightValidation.PL.csproj", "{13B5F568-F402-4A2A-9A23-0FDF0B5564E3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SilverlightValidation.Tests", "SilverlightValidation.Tests\SilverlightValidation.Tests.csproj", "{02CCF8C7-1311-453F-BF82-3564AD9E7B8C}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,10 +23,14 @@
 		{E65C6757-932B-4D01-9A8A-6D02F8FAA25A}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{E65C6757-932B-4D01-9A8A-6D02F8FAA25A}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{E65C6757-932B-4D01-9A8A-6D02F8FAA25A}.Release|Any CPU.Build.0 = Release|Any CPU
-		{12AE7560-AD64-4635-8A6B-772256FF0EDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{12AE7560-AD64-4635-8A6B-772256FF0EDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{12AE7560-AD64-4635-8A6B-772256FF0EDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{12AE7560-AD64-4635-8A6B-772256FF0EDD}.Release|Any CPU.Build.0 = Release|Any CPU
+		{13B5F568-F402-4A2A-9A23-0FDF0B5564E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{13B5F568-F402-4A2A-9A23-0FDF0B5564E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{13B5F568-F402-4A2A-9A23-0FDF0B5564E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{13B5F568-F402-4A2A-9A23-0FDF0B5564E3}.Release|Any CPU.Build.0 = Release|Any CPU
+		{02CCF8C7-1311-453F-BF82-3564AD9E7B8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{02CCF8C7-1311-453F-BF82-3564AD9E7B8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{02CCF8C7-1311-453F-BF82-3564AD9E7B8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{02CCF8C7-1311-453F-BF82-3564AD9E7B8C}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
--- a/SilverlightValidation/SilverlightValidation/Commands/RelayCommand.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-using System;
-using System.Windows.Input;
-
-namespace SilverlightValidation.Commands
-{
-    public class RelayCommand : ICommand
-    {
-        public event EventHandler CanExecuteChanged = delegate { };
-
-        readonly Action<object> _execute;
-        readonly Predicate<object> _canExecute;
-
-        public RelayCommand(Action<object> execute,
-                            Predicate<object> canExecute = null)
-        {
-            if (execute == null) throw new ArgumentNullException("execute");
-
-            _execute = execute;
-            _canExecute = canExecute;
-        }
-
-
-        public void UpdateCanExecuteCommand()
-        {
-            CanExecuteChanged(this, new EventArgs());
-        }
-
-
-        public bool CanExecute(object parameter)
-        {
-            return _canExecute == null || _canExecute(parameter);
-        }
-
-
-        public void Execute(object parameter)
-        {
-            _execute(parameter);
-        }
-    }
-}
--- a/SilverlightValidation/SilverlightValidation/Data/Factory.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-using System;
-using System.Collections.Generic;
-using SilverlightValidation.Models;
-
-namespace SilverlightValidation.Data
-{
-    public class Factory
-    {
-        public static IList<UserModel> CreateUserModels()
-        {
-            return new List<UserModel>(5)
-            {
-                new UserModel() { Username = "StevenH", Password = "Password1", Email = "steven@hotmail.com", DateOfBirth = new DateTime(1977, 09, 01), Description = ""},
-                new UserModel() { Username = "RichardJ", Password = "12N456a", Email = "dicky@gmail.com", DateOfBirth = new DateTime(1983, 03, 13), Description = "Loves .Net!"},
-                new UserModel() { Username = "BobbyP", Password = "pa33Word", Email = "bob@yahoo.co.uk", DateOfBirth = new DateTime(1992, 08, 30), Description = ""},
-                new UserModel() { Username = "DavidM", Password = "poIu789", Email = "daveyboy@marsh.com", DateOfBirth = new DateTime(1965, 06, 21), Description = "Java fan boy"},
-                new UserModel() { Username = "JessieJ", Password = "jlkJh567", Email = "jj@apple.co.uk", DateOfBirth = new DateTime(1990, 10, 15), Description = ""}
-            };
-        }
-    }
-}
--- a/SilverlightValidation/SilverlightValidation/Diagrams/Overview.cd	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ClassDiagram MajorVersion="1" MinorVersion="1">
-  <Class Name="SilverlightValidation.Models.UserModel">
-    <Position X="2.5" Y="1.75" Width="1.5" />
-    <TypeIdentifier>
-      <HashCode>AAAAAAAAACAgAAAAAQAAAAAAAAAQAEACAAAAAAAAABA=</HashCode>
-      <FileName>Models\UserModel.cs</FileName>
-    </TypeIdentifier>
-    <Lollipop Position="0.2" />
-  </Class>
-  <Class Name="SilverlightValidation.Validators.UserModelValidator" Collapsed="true">
-    <Position X="2" Y="7.75" Width="2" />
-    <TypeIdentifier>
-      <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAA=</HashCode>
-      <FileName>Validators\UserModelValidator.cs</FileName>
-    </TypeIdentifier>
-  </Class>
-  <Class Name="SilverlightValidation.ViewModels.UserListViewModel">
-    <Position X="6.25" Y="5.5" Width="2.75" />
-    <TypeIdentifier>
-      <HashCode>AAAAAAAAAAAAAAECAAAAAAAAAAAAABAYABEACAAAAAA=</HashCode>
-      <FileName>ViewModels\UserListViewModel.cs</FileName>
-    </TypeIdentifier>
-  </Class>
-  <Class Name="SilverlightValidation.ViewModels.UserViewModel">
-    <Position X="4.25" Y="1.75" Width="1.75" />
-    <TypeIdentifier>
-      <HashCode>UAAAoIAADCIgAAAAMYAACAAAAAAQABAKQEAAAAAgIAA=</HashCode>
-      <FileName>ViewModels\UserViewModel.cs</FileName>
-    </TypeIdentifier>
-    <Lollipop Position="0.2" />
-  </Class>
-  <Class Name="SilverlightValidation.ViewModels.ViewModelBase">
-    <Position X="6.25" Y="1.75" Width="2.75" />
-    <TypeIdentifier>
-      <HashCode>AAAAAAACAABQAAABAAAAAgAAgAAAAACIAAAAAAARAAA=</HashCode>
-      <FileName>ViewModels\ViewModelBase.cs</FileName>
-    </TypeIdentifier>
-    <Lollipop Position="0.2" />
-  </Class>
-  <Class Name="SilverlightValidation.Messages.UserViewResponseMessage">
-    <Position X="9.25" Y="5" Width="2.25" />
-    <TypeIdentifier>
-      <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAA=</HashCode>
-      <FileName>Messages\UserViewResponseMessage.cs</FileName>
-    </TypeIdentifier>
-  </Class>
-  <Interface Name="SilverlightValidation.Interfaces.ICloneable&lt;T&gt;">
-    <Position X="2.5" Y="4.5" Width="1.5" />
-    <TypeIdentifier>
-      <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA=</HashCode>
-      <FileName>Interfaces\ICloneable.cs</FileName>
-    </TypeIdentifier>
-  </Interface>
-  <Interface Name="SilverlightValidation.Interfaces.IUserModel">
-    <Position X="2.5" Y="5.75" Width="1.5" />
-    <TypeIdentifier>
-      <HashCode>AAAAAAAAACAgAAAAAQAAAAAAAAAQAAACAAAAAAAAAAA=</HashCode>
-      <FileName>Interfaces\IUserModel.cs</FileName>
-    </TypeIdentifier>
-  </Interface>
-  <Font Name="Segoe UI" Size="9" />
-</ClassDiagram>
\ No newline at end of file
--- a/SilverlightValidation/SilverlightValidation/Interfaces/ICloneable.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-namespace SilverlightValidation.Interfaces
-{
-  public interface ICloneable<T>
-  {
-    T Clone();
-  }
-}
--- a/SilverlightValidation/SilverlightValidation/Interfaces/IUserModel.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-using System;
-namespace SilverlightValidation.Interfaces
-{
-  public interface IUserModel
-  {
-    string Username { get; set; }
-    string Email { get; set; }
-    string Password { get; set; }
-    DateTime? DateOfBirth { get; set; }
-    string Description { get; set; }
-  }
-}
--- a/SilverlightValidation/SilverlightValidation/Messages/UserViewResponseMessage.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-using GalaSoft.MvvmLight.Messaging;
-using SilverlightValidation.ViewModels;
-
-namespace SilverlightValidation.Messages
-{
-    public class UserViewResponseMessage : MessageBase
-    {
-        public UserViewModel UserViewModel { get; set; }
-    }
-}
--- a/SilverlightValidation/SilverlightValidation/Models/UserModel.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-using System;
-using System.ComponentModel;
-using SilverlightValidation.Interfaces;
-
-namespace SilverlightValidation.Models
-{
-    public class UserModel : IUserModel, ICloneable<UserModel>
-    {
-        public string Username { get; set; }
-        public string Email { get; set; }
-        public string Password { get; set; }
-        public DateTime? DateOfBirth { get; set; }
-        public string Description { get; set; }
-
-        public static UserModel Create()
-        {
-            return new UserModel() { Username = "", Email = "", Password = "", DateOfBirth = null, Description = "" };
-        }
-
-        public UserModel Clone()
-        {
-            return (UserModel) this.MemberwiseClone(); 
-        }
-    }
-}
--- a/SilverlightValidation/SilverlightValidation/SilverlightValidation.csproj	Sat May 05 11:07:41 2012 +0100
+++ b/SilverlightValidation/SilverlightValidation/SilverlightValidation.csproj	Sat May 05 13:29:56 2012 +0100
@@ -63,16 +63,7 @@
     <Reference Include="FluentValidation">
       <HintPath>..\Libs\FluentValidation.dll</HintPath>
     </Reference>
-    <Reference Include="GalaSoft.MvvmLight.Extras.SL5, Version=4.0.21.32933, Culture=neutral, PublicKeyToken=e7f91b7703710fe7, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\Libs\GalaSoft.MvvmLight.Extras.SL5.dll</HintPath>
-    </Reference>
-    <Reference Include="GalaSoft.MvvmLight.SL5, Version=4.0.21.32885, Culture=neutral, PublicKeyToken=c114982fcf1a3a2e, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\Libs\GalaSoft.MvvmLight.SL5.dll</HintPath>
-    </Reference>
     <Reference Include="mscorlib" />
-    <Reference Include="System.ComponentModel.DataAnnotations, Version=5.0.5.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217, processorArchitecture=MSIL" />
     <Reference Include="System.Windows" />
     <Reference Include="system" />
     <Reference Include="System.Core" />
@@ -95,23 +86,13 @@
     <Compile Include="App.xaml.cs">
       <DependentUpon>App.xaml</DependentUpon>
     </Compile>
-    <Compile Include="Data\Factory.cs" />
-    <Compile Include="Interfaces\ICloneable.cs" />
-    <Compile Include="Interfaces\IUserModel.cs" />
-    <Compile Include="Messages\UserViewResponseMessage.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Commands\RelayCommand.cs" />
-    <Compile Include="ViewModels\UserListViewModel.cs" />
-    <Compile Include="Models\UserModel.cs" />
-    <Compile Include="Validators\UserModelValidator.cs" />
     <Compile Include="Views\UserListView.xaml.cs">
       <DependentUpon>UserListView.xaml</DependentUpon>
     </Compile>
     <Compile Include="Views\UserView.xaml.cs">
       <DependentUpon>UserView.xaml</DependentUpon>
     </Compile>
-    <Compile Include="ViewModels\UserViewModel.cs" />
-    <Compile Include="ViewModels\ViewModelBase.cs" />
   </ItemGroup>
   <ItemGroup>
     <ApplicationDefinition Include="App.xaml">
@@ -128,10 +109,14 @@
     </Page>
   </ItemGroup>
   <ItemGroup>
-    <None Include="Diagrams\Overview.cd" />
     <None Include="Properties\AppManifest.xml" />
   </ItemGroup>
-  <ItemGroup />
+  <ItemGroup>
+    <ProjectReference Include="..\SilverlightValidation.PL\SilverlightValidation.PL.csproj">
+      <Project>{13B5F568-F402-4A2A-9A23-0FDF0B5564E3}</Project>
+      <Name>SilverlightValidation.PL</Name>
+    </ProjectReference>
+  </ItemGroup>
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
--- a/SilverlightValidation/SilverlightValidation/Validators/UserModelValidator.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-using System;
-using FluentValidation;
-using SilverlightValidation.Interfaces;
-
-namespace SilverlightValidation.Validators
-{
-    public class UserModelValidator : AbstractValidator<IUserModel>
-    {
-        public UserModelValidator()
-        {
-            RuleFor(x => x.Username)
-                .Length(3, 8)
-                .WithMessage("Must be between 3-8 characters.");
-
-            RuleFor(x => x.Password)
-                .Matches(@"^\w*(?=\w*\d)(?=\w*[a-z])(?=\w*[A-Z])\w*$")
-                .WithMessage("Must contain lower, upper and numeric chars.");
-
-            RuleFor(x => x.Email)
-                .EmailAddress()
-                .WithMessage("A valid email address is required.");
-
-            RuleFor(x => x.DateOfBirth)
-                .Must(BeAValidDateOfBirth)
-                .WithMessage("Must be within 100 years of today.");
-        }
-
-        private bool BeAValidDateOfBirth(DateTime? dateOfBirth)
-        {
-            if (dateOfBirth == null) return false;
-            if (dateOfBirth.Value > DateTime.Today || dateOfBirth < DateTime.Today.AddYears(-100))
-                return false;
-            return true;
-        }
-    }
-}
--- a/SilverlightValidation/SilverlightValidation/ViewModels/UserListViewModel.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Windows.Input;
-using SilverlightValidation.Commands;
-using SilverlightValidation.Models;
-using SilverlightValidation.Validators;
-using SilverlightValidation.Views;
-using GalaSoft.MvvmLight.Messaging;
-using SilverlightValidation.Messages;
-
-namespace SilverlightValidation.ViewModels
-{
-    public class UserListViewModel
-    {
-        UserView window;
-
-        public UserListViewModel(IList<UserModel> models, UserModelValidator validator)
-        {
-            Data = new ObservableCollection<UserViewModel>();
-
-            foreach (var model in models)
-                Data.Add(new UserViewModel(model, validator));
-
-            AddCommand = new RelayCommand(AddCommandExecute);
-            DeleteCommand = new RelayCommand(DeleteCommandExecute);
-
-            Messenger.Default.Register<UserViewResponseMessage>(this, UserViewResponseMessageReceived);
-        }
-
-        private void UserViewResponseMessageReceived(UserViewResponseMessage userViewResponseMessage)
-        {
-            if (userViewResponseMessage.UserViewModel != null)
-                Data.Add(userViewResponseMessage.UserViewModel);
-            window.Close();
-        }
-
-        #region Properties
-
-        public ObservableCollection<UserViewModel> Data { get; set; }
-
-        public UserViewModel SelectedItem { get; set; }
-
-        #endregion
-
-        #region Commands
-
-        public ICommand AddCommand { get; set; }
-        public ICommand DeleteCommand { get; set; }
-
-        private void AddCommandExecute(object obj)
-        {
-            window = new UserView();
-            window.Show();
-        }
-
-        private void DeleteCommandExecute(object obj)
-        {
-            if (SelectedItem!=null)
-                Data.Remove(SelectedItem);
-        }
-
-        #endregion
-    }
-}
\ No newline at end of file
--- a/SilverlightValidation/SilverlightValidation/ViewModels/UserViewModel.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,223 +0,0 @@
-using System;
-using System.ComponentModel;
-using System.Linq;
-using System.Windows;
-using System.Windows.Input;
-using FluentValidation;
-using SilverlightValidation.Interfaces;
-using SilverlightValidation.Validators;
-using SilverlightValidation.Models;
-using SilverlightValidation.Commands;
-using GalaSoft.MvvmLight.Messaging;
-using SilverlightValidation.Messages;
-
-namespace SilverlightValidation.ViewModels
-{
-    public class UserViewModel : ViewModelBase, IUserModel, IEditableObject
-    {
-        #region Fields
-
-        private readonly UserModelValidator _validator;
-        private UserModel _data;
-        private UserModel _backup;
-
-        #endregion
-
-        #region Constructor
-
-        public UserViewModel(UserModel model, UserModelValidator validator)
-        {
-            _validator = validator;
-            _data = model;
-            _backup = model.Clone();
-
-            OkCommand = new RelayCommand(OkCommandExecute);
-            CancelCommand = new RelayCommand(CancelCommandExecute);
-        }
-
-        #endregion
-
-        #region Methods
-
-        private void SetProperties(IUserModel source)
-        {
-            _data.Username = source.Username;
-            _data.Password = source.Password;
-            _data.Email = source.Email;
-            _data.DateOfBirth = source.DateOfBirth;
-            _data.Description = source.Description;
-        }
-
-        #endregion
-
-        #region Properties
-
-        private const string UsernameProperty = "Username";
-        public string Username
-        {
-            get { return _data.Username; }
-            set
-            {
-                if (_data.Username != value)
-                {
-                    _data.Username = value;
-                    RaisePropertyChanged(UsernameProperty);
-                    IsChanged = true;
-                }
-
-                ClearError(UsernameProperty);
-                var validationResult = _validator.Validate(this, UsernameProperty);
-                if (!validationResult.IsValid)
-                    validationResult.Errors.ToList().ForEach(x => SetError(UsernameProperty, x.ErrorMessage));
-            }
-        }
-
-        private const string PasswordProperty = "Password";
-        public string Password
-        {
-            get { return _data.Password; }
-            set
-            {
-                if (_data.Password != value)
-                {
-                    _data.Password = value;
-                    RaisePropertyChanged(PasswordProperty);
-                    IsChanged = true;
-                }
-
-                ClearError(PasswordProperty);
-                var validationResult = _validator.Validate(this, PasswordProperty);
-                if (!validationResult.IsValid)
-                    validationResult.Errors.ToList().ForEach(x => SetError(PasswordProperty, x.ErrorMessage));
-            }
-        }
-
-        private const string EmailProperty = "Email";
-        public string Email
-        {
-            get { return _data.Email; }
-            set
-            {
-                if (_data.Email != value)
-                {
-                    _data.Email = value;
-                    RaisePropertyChanged(EmailProperty);
-                    IsChanged = true;
-                }
-
-                ClearError(EmailProperty);
-                var validationResult = _validator.Validate(this, EmailProperty);
-                if (!validationResult.IsValid)
-                    validationResult.Errors.ToList().ForEach(x => SetError(EmailProperty, x.ErrorMessage));
-            }
-        }
-
-        private const string DateOfBirthProperty = "DateOfBirth";
-        public DateTime? DateOfBirth
-        {
-            get { return _data.DateOfBirth; }
-            set
-            {
-                if (_data.DateOfBirth != value)
-                {
-                    _data.DateOfBirth = value;
-                    RaisePropertyChanged(DateOfBirthProperty);
-                    IsChanged = true;
-                }
-
-                ClearError(DateOfBirthProperty);
-                var validationResult = _validator.Validate(this, DateOfBirthProperty);
-                if (!validationResult.IsValid)
-                    validationResult.Errors.ToList().ForEach(x => SetError(DateOfBirthProperty, x.ErrorMessage));
-            }
-        }
-
-        private const string DescriptionProperty = "Description";
-        public string Description
-        {
-            get { return _data.Description; }
-            set
-            {
-                if (_data.Description != value)
-                {
-                    _data.Description = value;
-                    RaisePropertyChanged(DescriptionProperty);
-                    IsChanged = true;
-                }
-
-                ClearError(DescriptionProperty);
-                var validationResult = _validator.Validate(this, DescriptionProperty);
-                if (!validationResult.IsValid)
-                    validationResult.Errors.ToList().ForEach(x => SetError(DescriptionProperty, x.ErrorMessage));
-            }
-        }
-
-        #endregion
-
-        #region Commands
-
-        public ICommand OkCommand { get; set; }
-        public ICommand CancelCommand { get; set; }
-
-        private void OkCommandExecute(object obj)
-        {
-            RefreshToViewErrors();
-
-            if (IsChanged && !HasErrors)
-            {
-                // save here
-                Messenger.Default.Send<UserViewResponseMessage>(
-                    new UserViewResponseMessage() { UserViewModel = this });
-            }
-        }
-
-        // in case user hasn't touched the form
-        private void RefreshToViewErrors()
-        {
-            Username = _data.Username;
-            Password = _data.Password;
-            Email = _data.Email;
-            DateOfBirth = _data.DateOfBirth;
-        }
-
-        private void CancelCommandExecute(object obj)
-        {
-            Messenger.Default.Send<UserViewResponseMessage>(
-                new UserViewResponseMessage() { UserViewModel = null });
-        }
-        
-        #endregion
-
-        private void ResetFormData()
-        {
-            SetProperties(_backup);
-            ClearAllErrors();
-            IsChanged = false;
-        }
-
-        public bool IsChanged { get; private set; }
-
-        #region IEditableObject for datagrid
-
-        private bool inEdit;
-        public void BeginEdit()
-        {
-            if (inEdit) return;
-            inEdit = true;
-        }
-
-        public void CancelEdit()
-        {
-            if (!inEdit) return;
-            inEdit = false;
-            ResetFormData();
-        }
-
-        public void EndEdit()
-        {
-            if (!inEdit) return;
-        }
-
-        #endregion
-    }
-}
--- a/SilverlightValidation/SilverlightValidation/ViewModels/ViewModelBase.cs	Sat May 05 11:07:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Linq;
-
-namespace SilverlightValidation.ViewModels
-{
-    public class ViewModelBase : INotifyPropertyChanged, INotifyDataErrorInfo
-    {
-        #region INotifyPropertyChanged method plus event
-
-        public event PropertyChangedEventHandler PropertyChanged = delegate { };
-
-        protected void RaisePropertyChanged(string propertyName)
-        {
-            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
-        }
-
-        #endregion
-
-        #region INotifyDataErrorInfo methods and helpers
-
-        private readonly Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>();
-
-        public void SetError(string propertyName, string errorMessage)
-        {
-            if (!_errors.ContainsKey(propertyName))
-                _errors.Add(propertyName, new List<string> { errorMessage });
-
-            RaiseErrorsChanged(propertyName);
-        }
-
-        protected void ClearError(string propertyName)
-        {
-            if (_errors.ContainsKey(propertyName))
-            {
-                _errors.Remove(propertyName);
-                RaiseErrorsChanged(propertyName);
-            }
-        }
-
-        protected void ClearAllErrors()
-        {
-            var errors = _errors.Select(error => error.Key).ToList();
-
-            foreach (var propertyName in errors)
-                ClearError(propertyName);
-        }
-
-        public void RaiseErrorsChanged(string propertyName)
-        {
-            ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
-        }
-
-        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged = delegate { };
-
-        public IEnumerable GetErrors(string propertyName)
-        {
-            if (propertyName == null) return null;
-            return _errors.ContainsKey(propertyName)
-                    ? _errors[propertyName]
-                    : null;
-        }
-
-        public bool HasErrors
-        {
-            get { return _errors.Count > 0; }
-        }
-
-        #endregion
-    }
-}
--- a/SilverlightValidation/SilverlightValidation/Views/UserListView.xaml.cs	Sat May 05 11:07:41 2012 +0100
+++ b/SilverlightValidation/SilverlightValidation/Views/UserListView.xaml.cs	Sat May 05 13:29:56 2012 +0100
@@ -15,7 +15,7 @@
             InitializeComponent();
             HtmlPage.Document.SetProperty("title", "Silverlight Validation");
 
-            vm = new UserListViewModel(Factory.CreateUserModels(), new UserModelValidator());
+            vm = new UserListViewModel(new UserView(), Factory.CreateUserModels(), new UserModelValidator());
             this.DataContext = vm;
         }