Posts by roboblob
Custom Silverlight TextBox control that immediately updates DataBound Text property in TwoWay binding
12Standard Silverlight TextBox control is very useful but has one strange behavior: if you use TwoWay data binding and bind some property to controls Text property, when users type text into the control, this change is not propagated to the bound property until the control loses its focus.
This can be very annoying if you have MVVM application and you have some kind of real-time filter that needs to update some data as-you-type.
Problem is that TextBox control does not call BindingExpression.UpdateSource when its Text property is changed so we have to do that manually in order to fix this issue.
To fix this once and for all I have created simple custom control ImmediateTextBox that inherits the standard TextBox and just calls BindingExpression.UpdateSource for TextBox.TextProperty whenever text is changed.
Here is all the code that is in our custom control:
using System.Windows.Controls;
namespace ImmediateDataBindingTextBox
{
public class ImmediateTextBox : TextBox
{
public ImmediateTextBox()
{
this.Loaded += ImmediateTextBox_Loaded;
}
void ImmediateTextBox_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
this.TextChanged += ImmediateTextBox_TextChanged;
}
void ImmediateTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var tb = sender as TextBox;
if (tb != null)
{
var be = tb.GetBindingExpression(TextBox.TextProperty);
if (be != null)
{
be.UpdateSource();
}
}
}
}
}
And here is the demo application that shows this in action.
In sample app you have standard TextBox and our custom ImmediateTextBox that are both bound to some property in ViewModel using TwoWay binding.
Below is TextBlock also bound to same property to show the current value of the property.
If you type text into standard TextBox the text in TextBlock will not be updated until TextBox loses its focus and if you type text into our custom control you will see the changes propagated to the underlying property immediately.
If you want to use this control you can download sample Visual Studio 2010 Solution
Hope someone can find this useful when doing MVVM style applications where you cannot just reach for the code in code-behind to fix problems like this
Silverlight MergedDictionaries – using styles and resources from Class Libraries
5If you were developing larger Silverlight/WPF applications and trying to keep things like styles, control templates and other resources organized it can become really hard.
Prior to Silverlight 3 it was hell to be honest
You had to scatter resources all around your application, on control level and put global ones in App.xaml and soon it would all grow beyond control.
But then nice people from Microsoft introduced lovely little feature called MergedDictionaries that allows you to combine the resources from different places in your application.
The beauty of this simple technique is that you can use resources from different files that can even reside in different Class Libraries in your project and just ‘reference’ them in the application level (App.xaml) and they will immediately become available to all the controls in your application.
Not to mention the moment of reuse: you can group your application resources into assemblies, for example one can hold the Styles, another can contain Control Templates, third can have text resources etc and then you can just reference them in any project and easily (re)use them.
So lets see how to actually accomplish this.
Luckily its very simple. We just need to add few lines to our App.xaml file:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ResourceDictionariesInLib.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ResourceDictionariesInLib.BasicStyles;component/StylesForShapes.xaml" />
<ResourceDictionary Source="/ResourceDictionariesInLib.FontStyles;component/StylesForFonts.xaml" />
<ResourceDictionary Source="LocalStyles/BasicStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
As you see here I’m using resources from two different Silverlight Class Libraries and one is from local subfolder called “LocalStyles”.
The format is clear, for resources in DLLs you use:
Source=”/AssemblyName;component/FileName.xaml”
The “component” part is just a keyword that tells the parser that resource is in referenced DLL.
One important catch here is if you are merging resources from DLLs than you need to actually add references to those Class Libraries that hold your resources so in this case i had to Add Reference to two DLLs: ResourceDictionariesInLib.BasicStyles.dll and ResourceDictionariesInLib.FontStyles.dll.
Format for the resource file in the application is self-explanatory.
In order to create a xaml file in some Class Library to hold resources just choose Add->New Item and then select SilverlightResourceDictionary from the list.
Also its important to state here that you can put MergedDictionaries at every level, meaning that you can put them to App.xaml and then those merged resources will be available to every element of your application, but also you can place MergedDictionaries in the CustomControl (in CustomControl.Resources) and then this resources will be available only to this control.
So lets see how those MergedDictionaries of resources can be used.
In the StylesForShapes.xaml file i have some background gradient brushes:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<LinearGradientBrush x:Key="EllipseFillBrush" EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="#FFD41313" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="RectangleFillBrush" EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="#FF3AD859" Offset="1" />
</LinearGradientBrush>
</ResourceDictionary>
So since i referenced StylesForShapes.xaml file in MergedDictionaries in my App.xaml file i can use styles from that file in any Silverlight control in the whole application.
<Grid x:Name="LayoutRoot" Background="White" Height="348" Width="489">
<Ellipse Fill="{StaticResource EllipseFillBrush}" />
<Rectangle Fill="{StaticResource RectangleFillBrush}" />
</Grid>
You can do the same for any other property like FontSize or FontFamilly.
Just extract property value to a resource and then reuse it in your app.
Another very nice thing about MergedDictionaries is that they are supported by Visual Studio 2010 and Blend 3/4 so if you have DLLs with resources and you merge them in App.xaml then when you are extracting new resources you can specify those resource files in DLL’s as the place where that newly extracted resource will be created.
Here is the example:
In Visual Studio create UserControl and put an Ellipse element on it and set its Fill property to be some nice GradientBrush and then click on the black diamond symbol to the right of the Fill property and in the pop-up menu choose option Extract value to Resource:
After clicking on the Extract Value to Resource menu item you will need to choose where to save the newly created resource and you can here choose any of the resource xaml files in your Class Libraries like this:
So here is how a sample page that uses MergedDictionaries to set styles and fonts on its controls looks like:

And here is the Visual Studio 2010 demo solution.
Have fun!
Unit Testing Modal Dialogs in MVVM and Silverlight 4
0As feedback to my recent post on Modal Dialogs in MVVM and Silverlight 4 I have received comments that the solution is not easy to Unit Test so i decided to create small blog posts on this subject just to show how simple and clean it is to do this.
So for those who are too lazy to read my original modal dialog post here is a quick reminder:
- I presented a simple solution how to abstract modal dialogs and message boxes in Silverlight 4 and call them from your ViewModel and act according to the results returned from those modal dialogs.
- I used Silverlight’s ChildWindow control because it was perfect fit for that job.
- Important thing is to say that ChildWindow control was used as implementation (with its ViewModel off course) but was hidden by abstractions (like IModalWindow and IModalWindowService) so it can easily be changed by some other implementation and unit tested, mocked out etc.
So in this post i will use the same simple Demo Application for the previous modal dialogs post but I will add few Unit Tests using Silverlight Unit Testing Framework and Silverlight verstion of RhinoMocks.
Our Sample app is very simple and just shows a view with list of some User entities.
Each of users can be edited by clicking on EDIT button next to them – this shows a modal dialog with User editor, we can change details and save them by clicking on OK or CANCEL.
Also there is option to delete each User by clicking on the DEL button – Message Box is shown with OK/Cancel buttons – these are very common scenarios for every LOB application so that’s why i picked them.
I must admit that i improved my framework since the previous post – I changed the signature of the IModalDialogService a little because now in my framework i have a IViewInitializationService that wires up ViewModels with Views so all this is used in this posts just to show it off
(more on the IViewInitializationService and the new way how i wire up ViewModels and View in one of the next posts).
So first let’s see the changes made to the IModalDialogView that is the abstraction of the actual modal dialog to be shown:
public interface IModalWindowView : IView
{
bool? DialogResult { get; set; }
event EventHandler Closed;
void Show();
void Close();
}
So the real ChildWindow that will be our dialog only needs to be marked as implementor of IModalWindowView interface with no additional code needed since this interface contains only methods and properties that ChildWindow already implements:
public partial class EditUserModalDialogView : IModalWindowView
{
public EditUserModalDialogView()
{
InitializeComponent();
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
}
}
Also you could see that our IModalDialogView implements our old friend – IView:
public interface IView
{
object FindName(string name);
object DataContext { get; set; }
string Name { get; set; }
event RoutedEventHandler Loaded;
}
Again nothing to implement here – no code to add – because ChildWindow already implements all this since its inheriting the ContentContol that has all this.
So now lets see the MainPageViewModel for our MainPageView that will actually show the modal dialogs and message boxes:
public class MainPageViewModel : ViewModel
{
private readonly IModalDialogService modalDialogService;
private readonly IMessageBoxService messageBoxService;
private ObservableCollection<User> users = new ObservableCollection<User>();
public MainPageViewModel(IModalDialogService modalDialogService, IMessageBoxService messageBoxService)
{
this.modalDialogService = modalDialogService;
this.messageBoxService = messageBoxService;
this.Users = new ObservableCollection<User>();
for (int i = 1; i < 6; i++ )
{
this.Users.Add(new User {Username = string.Format("Admin User {0}",
new Random((int)DateTime.Now.Ticks).Next(10,100)), IsAdmin = true});
Thread.Sleep(100);
}
this.ShowUserCommand =
new DelegateCommand<User>(userInstanceToEdit =>
{
this.modalDialogService.ShowDialog<EditUserModalDialogViewModel>
(
userInstanceToEdit,
(dialog, returnedViewModelInstance) =>
{
if (dialog.DialogResult.HasValue && dialog.DialogResult.Value)
{
var oldItem = this.Users.FirstOrDefault( u => u.Id == userInstanceToEdit.Id);
var oldPos = this.Users.IndexOf(oldItem);
if (oldPos > -1)
{
this.Users.RemoveAt(oldPos);
this.Users.Insert(oldPos, returnedViewModelInstance.User);
}
}
});
});
this.DeleteUserCommand = new DelegateCommand<User>
(p =>
{
var result = this.messageBoxService.Show(string.Format(
"Are you sure you want to delete user {0} ???", p.Username),
"Please Confirm", GenericMessageBoxButton.OkCancel);
if (result == GenericMessageBoxResult.Ok)
{
this.Users.Remove(p);
}});
}
public ObservableCollection<User> Users
{
get { return users; }
set { users = value;
this.OnPropertyChanged("Users");
}
}
private ICommand showUserCommand;
public ICommand ShowUserCommand
{
get { return showUserCommand; }
set { showUserCommand = value;
this.OnPropertyChanged("ShowUserCommand");
}
}
private ICommand deleteUserCommand;
public ICommand DeleteUserCommand
{
get { return deleteUserCommand; }
set { deleteUserCommand = value;
this.OnPropertyChanged("DeleteUserCommand");
}
}
}
As you see ViewModel is simple class and it just has a list of Users to be shown by its View and important things to notice here are two commands for editing and deleting single user.
ShowUserCommand shows modal dialog for editing single user, and DeleteUserCommand just shows MessageBox for confirmation of deletion with OK and Cancel buttons.
So now comes the fun part, lets write unit tests for those commands:
First UnitTest checks that our ShowUserCommand shows the modal dialog for editing the user (using the IModalDialogService). We put expectation on our IModalDialogService mock and invoke our command on ViewModel and verify all expectations afterwards.
Here is the code:
[TestMethod]
public void ShowUserCommand_WhenCalledWithSpecificUser_ShowsModalDialogByPassingThatUserAsInitParam()
{
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
modalDialogService.Expect(
p => p.ShowDialog<EditUserModalDialogViewModel>(null, null))
.Constraints(
Is.Same(userToSend),
Is.TypeOf(typeof(Action<IModalWindowView, EditUserModalDialogViewModel>)))
.Repeat.Once();
viewModel.ShowUserCommand.Execute(userToSend);
modalDialogService.VerifyAllExpectations();
}
We first get our ViewModel with Rhino-mocked instances of IModalDialogService and IMessageBoxService and some test Users by calling this methods:
private static ObservableCollection<User> GenerateSampleUsers()
{
return new ObservableCollection<User>()
{
new User() {Username = "user 1"},
new User() {Username = "user 2"},
new User() {Username = "user 3"}
};
}
private MainPageViewModel GetInitializedAndMockedViewModel()
{
this.modalDialogService = MockRepository.GenerateMock<IModalDialogService>();
this.messageBoxService = MockRepository.GenerateMock<IMessageBoxService>();
return new MainPageViewModel(this.modalDialogService, this.messageBoxService);
}
So that was easy or what?
Lets go to next Unit Test. Lets check that when we call ShowUserCommand with instance of User that when it shows dialog and dialog returns true as its DialogResult – that we replace the original User in ViewModel’s list of Users with the one we got from the modal dialog:
[TestMethod]
public void ShowUserCommand_WhenCalledWithSpecificUserAndOnModalDialogResultIsTrue_ShouldReplaceTheOriginalUserInstanceWithOneReturnedFromModel()
{
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
var dialog = MockRepository.GenerateMock<IModalWindowView>();
dialog.Expect(p => p.DialogResult).Return(true);
var mockViewModel = MockRepository.GenerateStub<EditUserModalDialogViewModel>();
mockViewModel.User = new User() {Username = "mocked"};
modalDialogService.Expect(
p => p.ShowDialog<EditUserModalDialogViewModel>(null, null))
.Constraints(
Is.Same(userToSend),
Is.TypeOf(typeof (Action<IModalWindowView, EditUserModalDialogViewModel>)))
.Repeat.Once().WhenCalled(
m =>
{
var action = (m.Arguments[1] as Action<IModalWindowView, EditUserModalDialogViewModel>);
if (action != null)
{
action.Invoke(dialog, mockViewModel);
}
});
viewModel.ShowUserCommand.Execute(userToSend);
Assert.AreEqual("mocked", viewModel.Users[1].Username);
}
And here is the unit test that checks the DeleteUserCommand so that it actually deletes the user from the ViewModel’s list of users if OK button was clicked on the shown message box:
[TestMethod]
public void DeleteUserCommand_WhenCalledWithSpecificUserAndCallToMessageBoxServiceReturnsOk_ShouldDeleteThatUser()
{
// arrange
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
this.messageBoxService.Expect(p => p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
Is.Anything(), Is.Anything(),
Is.Anything()).Return(GenericMessageBoxResult.Ok);
// act
viewModel.DeleteUserCommand.Execute(userToSend);
// assert user is not there anymore
Assert.IsFalse(viewModel.Users.Any( u => u.Username == userToSend.Username));
}
So it turned out that its quite simple to test Modal Dialogs as long as you have the proper abstractions in place ![]()
You can open this page to see all the unit tests running in browser.
Those tests are actually running on the code from the sample demo app!
And as you see all the Unit Tests are green, and the world is safe again
Here is the code for all the tests, that is – all 9 of them:
namespace UnitTestingModalDialogs.Tests
{
[TestClass]
public class MainPageViewModelTests
{
private IModalDialogService modalDialogService;
private IMessageBoxService messageBoxService;
private static ObservableCollection<User> GenerateSampleUsers()
{
return new ObservableCollection<User>()
{
new User() {Username = "user 1"},
new User() {Username = "user 2"},
new User() {Username = "user 3"}
};
}
private MainPageViewModel GetInitializedAndMockedViewModel()
{
this.modalDialogService = MockRepository.GenerateMock<IModalDialogService>();
this.messageBoxService = MockRepository.GenerateMock<IMessageBoxService>();
return new MainPageViewModel(this.modalDialogService, this.messageBoxService);
}
[TestMethod]
public void ShowUserCommand_WhenCalledWithSpecificUser_ShowsModalDialogByPassingThatUserAsInitParam()
{
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
modalDialogService.Expect(
p => p.ShowDialog<EditUserModalDialogViewModel>(null, null))
.Constraints(
Is.Same(userToSend),
Is.TypeOf(typeof(Action<IModalWindowView, EditUserModalDialogViewModel>)))
.Repeat.Once();
viewModel.ShowUserCommand.Execute(userToSend);
modalDialogService.VerifyAllExpectations();
}
[TestMethod]
public void ShowUserCommand_WhenCalledWithSpecificUserAndOnModalDialogResultIsTrue_ShouldReplaceTheOriginalUserInstanceWithOneReturnedFromModel()
{
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
var dialog = MockRepository.GenerateMock<IModalWindowView>();
dialog.Expect(p => p.DialogResult).Return(true);
var mockViewModel = MockRepository.GenerateStub<EditUserModalDialogViewModel>();
mockViewModel.User = new User() {Username = "mocked"};
modalDialogService.Expect(
p => p.ShowDialog<EditUserModalDialogViewModel>(null, null))
.Constraints(
Is.Same(userToSend),
Is.TypeOf(typeof (Action<IModalWindowView, EditUserModalDialogViewModel>)))
.Repeat.Once().WhenCalled(
m =>
{
var action = (m.Arguments[1] as Action<IModalWindowView, EditUserModalDialogViewModel>);
if (action != null)
{
action.Invoke(dialog, mockViewModel);
}
});
viewModel.ShowUserCommand.Execute(userToSend);
Assert.AreEqual("mocked", viewModel.Users[1].Username);
}
[TestMethod]
public void ShowUserCommand_WhenCalledWithSpecificUserAndOnModalDialogResultIsFalse_ShouldNotReplaceTheItemInViewModelWithOneReceivedFromDialog()
{
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
var dialog = MockRepository.GenerateMock<IModalWindowView>();
dialog.Expect(p => p.DialogResult).Return(false);
var mockViewModel = MockRepository.GenerateStub<EditUserModalDialogViewModel>();
mockViewModel.User = new User() { Username = "mocked" };
modalDialogService.Expect(
p => p.ShowDialog<EditUserModalDialogViewModel>(null, null))
.Constraints(
Is.Same(userToSend),
Is.TypeOf(typeof(Action<IModalWindowView, EditUserModalDialogViewModel>)))
.Repeat.Once().WhenCalled(
m =>
{
var action = (m.Arguments[1] as Action<IModalWindowView, EditUserModalDialogViewModel>);
if (action != null)
{
action.Invoke(dialog, mockViewModel);
}
});
viewModel.ShowUserCommand.Execute(userToSend);
Assert.AreNotEqual("mocked", viewModel.Users[1].Username);
}
[TestMethod]
public void ShowUserCommand_WhenCalledWithSpecificUserAndOnModalDialogResultIsNull_ShouldNotReplaceTheItemInViewModelWithOneReceivedFromDialog()
{
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
var dialog = MockRepository.GenerateMock<IModalWindowView>();
dialog.Expect(p => p.DialogResult).Return(null);
var mockViewModel = MockRepository.GenerateStub<EditUserModalDialogViewModel>();
mockViewModel.User = new User() { Username = "mocked" };
modalDialogService.Expect(
p => p.ShowDialog<EditUserModalDialogViewModel>(null, null))
.Constraints(
Is.Same(userToSend),
Is.TypeOf(typeof(Action<IModalWindowView, EditUserModalDialogViewModel>)))
.Repeat.Once().WhenCalled(
m =>
{
var action = (m.Arguments[1] as Action<IModalWindowView, EditUserModalDialogViewModel>);
if (action != null)
{
action.Invoke(dialog, mockViewModel);
}
});
viewModel.ShowUserCommand.Execute(userToSend);
Assert.AreNotEqual("mocked", viewModel.Users[1].Username);
}
[TestMethod]
public void DeleteUserCommand_WhenCalledWithSpecificUser_ShouldCallMessageBoxServiceWithSomeTextThatContainsThatUsersUsername()
{
// arrange
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
this.messageBoxService.Expect(p => p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
Is.Matching<string>(txt => txt.Contains(userToSend.Username)), Is.Anything(),
Is.Equal(GenericMessageBoxButton.OkCancel)).Return(GenericMessageBoxResult.Ok);
// act
viewModel.DeleteUserCommand.Execute(userToSend);
// assert
this.messageBoxService.VerifyAllExpectations();
}
[TestMethod]
public void DeleteUserCommand_WhenCalledWithSpecificUser_ShouldCallMessageBoxServiceWithOkCancelParamForButtons()
{
// arrange
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
this.messageBoxService.Expect(p => p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
Is.Anything(), Is.Anything(),
Is.Equal(GenericMessageBoxButton.OkCancel)).Return(GenericMessageBoxResult.Ok);
// act
viewModel.DeleteUserCommand.Execute(userToSend);
// assert
this.messageBoxService.VerifyAllExpectations();
}
[TestMethod]
public void DeleteUserCommand_WhenCalledWithSpecificUserAndCallToMessageBoxServiceReturnsOk_ShouldDeleteThatUser()
{
// arrange
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
this.messageBoxService.Expect(p => p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
Is.Anything(), Is.Anything(),
Is.Anything()).Return(GenericMessageBoxResult.Ok);
// act
viewModel.DeleteUserCommand.Execute(userToSend);
// assert user is not there anymore
Assert.IsFalse(viewModel.Users.Any( u => u.Username == userToSend.Username));
}
[TestMethod]
public void DeleteUserCommand_WhenCalledWithSpecificUserAndCallToMessageBoxServiceReturnsCancel_ShouldNOTDeleteThatUser()
{
// arrange
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
this.messageBoxService.Expect(p => p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
Is.Anything(), Is.Anything(),
Is.Anything()).Return(GenericMessageBoxResult.Cancel);
// act
viewModel.DeleteUserCommand.Execute(userToSend);
// assert user is not there anymore
Assert.IsTrue(viewModel.Users.Any(u => u.Username == userToSend.Username));
}
[TestMethod]
public void DeleteUserCommand_WhenCalledWithSpecificUserAndCallToMessageBoxServiceReturnsCancel_ShouldNOTDeleteAnyUser()
{
// arrange
var viewModel = GetInitializedAndMockedViewModel();
viewModel.Users = GenerateSampleUsers();
var userToSend = viewModel.Users[1];
this.messageBoxService.Expect(p => p.Show(null, null, GenericMessageBoxButton.OkCancel)).Constraints(
Is.Anything(), Is.Anything(),
Is.Anything()).Return(GenericMessageBoxResult.Cancel);
var usersCountBefore = viewModel.Users.Count;
// act
viewModel.DeleteUserCommand.Execute(userToSend);
// assert user is not there anymore
Assert.AreEqual(usersCountBefore, viewModel.Users.Count);
}
}
}
If you want to investigate further download the Visual Studio 2010 solution and play with it – feel free to use the code as you wish and remember to have fun!
















