Showing posts with label Silverlight. Show all posts
Showing posts with label Silverlight. Show all posts

Saturday, 21 June 2008

Silverlight 2.0 Beta 2 - Update on creating a user control to be used as a base class

It appears I was wrong in my previous post.

The ContentPropertyAttribute is seemingly ignored! Although it compiles, and can be edited in Blend, you get a XamlParseException when you try to run it:

"ShellBase does not support Grid as content"

The solution is to manually specify the content property in your Xaml (which kind of sucks!). Strange as this all used to work in Beta 1 (although there were other issues involving namespace parsing which have now been fixed). The correct Xaml looks like this:

<Silverstone:ShellBase x:Class="Silversocial.Client.Views.Shell"

   xmlns="http://schemas.microsoft.com/client/2007"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:Silverstone="clr-namespace:Silverstone;assembly=Silverstone">

    <Silverstone:ShellBase.Content>

        <Grid Background="#FF000000">

 

        </Grid>

    </Silverstone:ShellBase.Content>

</Silverstone:ShellBase>

I think (hope) this may be a bug but I will try to confirm this and update my blog if I find out any more.

Thursday, 19 June 2008

MessageBox.Show in Silverlight

Well, it's kind of obvious to anyone that has done any browser based Javascript development, but thought this was worth posting for those of you that do a lot of Windows Development and are wondering how to show a MessageBox in Silverlight. For those of you that have tried it:

MessageBox.Show("Hello world!");

OOPS! Compiler error... that doesn't work, Silverlight does not have a MessageBox class like WPF / WinForms / Win32. Instead, you can ask the browser to do this for you. How do you do this you might ask?

HtmlWindow.Alert("Hello world!");

This is the exact equivalent of the javascript alert function, which would look something like this:

alert("Hello world!");

So what if you want more control? Well, you will find the browser does not provide quite as much as desktop apps for this. In WPF, you can control the message, the title, the icon, the colours, buttons and more! Alert() will simply display a normal dialog with an OK button and the message, and a browser dependent title. The other option the browser gives you is to display a message box with "OK" and "Cancel" options and to be able to read the result of what the user chooses. In WPF you would do:

DialogResult result = MessageBox.Show("Shall I proceed?", "Title", MessageBoxButtons.OKCancel);
if (result == MessageBoxResult.OK)
{
  // process the OK
}

In Silverlight, the equivalent is:

bool result = HtmlPage.Window.Confirm("Shall I proceed?");
if (result)
{
  // process the OK
}

Tuesday, 17 June 2008

Silverlight 2.0 Beta 2 - Creating a user control to be used as a base class

Little tip here that I worked out whilst trying to get the ShellBase class from Silverstone working in the XAML editor and Expression blend.

I started off with an abstract class which derived from UserControl, like follows:

    public abstract class ShellBase : UserControl, IShell

    {

        //... some code

    }

Unfortunately, neither Expression Blend nor Visual Studio's Cider designer likes this, they need to create an instance of the base class for some reason. You get an error message saying it couldn't create an instance of it. Removing the abstract constraint solves this (though violates OO, but I don't mind in this instance!).

Now I have some XAML which looks like this for defining my actual Shell:

<Silverstone:ShellBase x:Class="Silversocial.Client.Views.Shell"

   xmlns="http://schemas.microsoft.com/client/2007"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:Silverstone="clr-namespace:Silverstone;assembly=Silverstone">

    <Grid x:Name="LayoutRoot" Background="Black">

 

    </Grid>

</Silverstone:ShellBase>

VS and blend now complain because ShellBase does allow content to be added. The solution I discovered was fairly simple and was twofold:

1. Add a property called Content which shadows the UserControl's Content property and redirects to it

2. Add a ContentProperty attribute to the ShellBase which points to the Content property

    [ContentProperty("Content")]

    public class ShellBase : UserControl, IShell

    {

        /// <summary>

        ///    Redefine the base class's content property to keep the designers happy

        /// </summary>

        public new UIElement Content

        {

            get { return base.Content; }

            set { base.Content = value; }

        }

And that's it! Designer support enabled!

Hope this helps...

Neil

Update - 20/06/2008

It appears I was wrong about the ContentProperty attribute, it doesn't work. See this post for more info

Monday, 19 May 2008

MVC Architecting Silverlight Applications Part 3 - Testing the ViewModel

In Part 2 of this series, I built a small class used to model our Login page - LoginViewModel.

In this post, I will demonstrate how to unit test this class to show that it behaves as expected. This is pretty essential as we want to be sure the class works properly before handing it over to our designer to build a view for!

I will be using TestDriven.NET's new Silverlight unit testing support which I blogged about earlier. This is unbelievably simple - just download and install the project template and then create a new Silveright NUnit Project called Silversocial.Client.Modules.Test

Building some test doubles


Before we can start unit testing our LoginViewModel, we need to fake out the dependencies. Given that there currently exists no mocking framework for Silverlight ( are you listening Ayende? ;-> ) we will manually build some stubs for our dependencies and then reuse them in our tests.

It is quite easy to way manually to build reusable stubs for an interface of your choosing. I simply follow these rules:
  • Use "explicit interface implementations" for all members

  • Implement properties as normal properties with a backing field (or as automatic properties if you'd prefer)

  • Implement methods by delegating the entire method body to a public event handler with the same signature and name as the method. Set the event handler to empty delegate to avoid null checks

  • Implement events by delegating the add/remove to a public event handler with the same signature as the event. Set the event handler to empty delegate to avoid null checks


Here is the code for the stub for the IAppShell interface.

using Silverstone;

 

namespace Silversocial.Client.Modules.Tests.Stubs

{

    public class AppShellStub : IAppShell

    {

        private User user;

        private IView view;

 

        public User User

        {

            get { return this.user; }

        }

 

        public IView View

        {

            get { return this.view; }

        }

 

        User IAppShell.User

        {

            get { return this.user; }

            set { this.user = value; }

        }

 

        void IShell.SetView(IView view)

        {

            this.view = view;

        }

    }

}


And now the stub for the ILoginDataProvider, also following the guidelines set above:

using System;

 

namespace Silversocial.Client.Modules.Tests.Stubs

{

    public class LoginDataProviderStub : ILoginDataProvider

    {

        private EventHandler<ValidateUserCompletedEventArgs> validateUserCompleted = delegate { };

 

        public Action<User> ValidateUser = delegate { };

 

        public void RaiseValidateUserCompleted(ValidateUserCompletedEventArgs args)

        {

            this.validateUserCompleted(this, args);

        }

 

        event EventHandler<ValidateUserCompletedEventArgs> ILoginDataProvider.ValidateUserCompleted

        {

            add { this.validateUserCompleted += value; }

            remove { this.validateUserCompleted -= value; }

        }

 

        void ILoginDataProvider.ValidateUser(User user)

        {

            this.ValidateUser(user);

        }

    }

}


We will create a "ViewStubBase" which implements the IView interface itself. This will form the base class for all other stubs of the views.

using System;

using Silverstone;

 

namespace Silversocial.Client.Modules.Tests.Stubs

{

    public abstract class ViewStubBase : IView

    {

        public Action OnLoad = delegate { };

        public Action OnUnload = delegate { };

 

        void IView.OnLoad()

        {

            this.OnLoad();

        }

 

        void IView.OnUnload()

        {

            this.OnLoad();

        }

    }

}


And now the stub for the ILoginView interface. As you can see we just implement the LoginUnsuccessful method and call a public event handler which does nothing by default. The allows the test to listen to the method being called if it wants to, and can for example validate if it is called or not.

using System;

 

namespace Silversocial.Client.Modules.Tests.Stubs

{

    public class LoginViewStub : ViewStubBase, ILoginView

    {

        public Action LoginUnsuccessful = delegate { };

 

        void ILoginView.LoginUnsuccessful()

        {

            this.LoginUnsuccessful();

        }

    }

}


The other views are just empty classes for now. The first:

namespace Silversocial.Client.Modules.Tests.Stubs

{

    public class FriendListStub : ViewStubBase, IFriendListView

    {

    }

}


And the other...

namespace Silversocial.Client.Modules.Tests.Stubs

{

    public class RegisterStub : ViewStubBase, IRegisterView

    {

    }

}


The test fixture



Finally it's time to implement the test fixture, just using the standard NUnit syntax for defining the tests and setup method. The SetUp creates all the stubs, so they can be used by each test.

Note I am using the "AAA" pattern which was recently coined by Ayende for RhinoMocks 3.5 - I really like it! This is the way I have written most of my tests in the past, and it's nice to have a formal name for the stages undergone (especially when it's an alliterism)

Here are the tests:

using NUnit.Framework;

using Silversocial.Client.Modules.Tests.Stubs;

using Silverstone;

 

namespace Silversocial.Client.Modules.Tests

{

    [TestFixture]

    public class LoginViewModelTester

    {

        private LoginViewStub loginViewStub;

        private AppShellStub shellStub;

        private FriendListStub friendListStub;

        private RegisterStub registerStub;

        private LoginDataProviderStub dataProviderStub;

        private LoginViewModel viewModel;

 

        [SetUp]

        public void SetUp()

        {

            this.shellStub = new AppShellStub();

            this.friendListStub = new FriendListStub();

            this.registerStub = new RegisterStub();

            this.dataProviderStub = new LoginDataProviderStub();

            this.viewModel = new LoginViewModel(shellStub, dataProviderStub, friendListStub, registerStub);

 

            this.loginViewStub = new LoginViewStub();

            ((IViewModel) this.viewModel).SetView(this.loginViewStub);

        }

 

        [Test]

        public void Login_WithoutUsernameAndPassword_CannotExecute()

        {

            Assert.IsFalse(this.viewModel.Login.CanExecute(null));

        }

 

        [Test]

        public void Login_WithUsernameAndPassword_CanExecute()

        {

            // Arrange

            this.viewModel.User.Username = "abc";

            this.viewModel.User.Password = "abc";

 

            // Assert

            Assert.IsTrue(this.viewModel.Login.CanExecute(null));

        }

 

        [Test]

        public void Login_BeforeCompleted_IsLoggingInIsTrue()

        {

            // Act

            this.viewModel.Login.Execute(null);

 

            // Assert

            Assert.IsTrue(this.viewModel.IsLoggingIn);

        }

 

        [Test]

        public void Login_AfterCompleted_IsLoggingInIsFalse()

        {

            // Act

            this.viewModel.Login.Execute(null);

            this.dataProviderStub.RaiseValidateUserCompleted(new ValidateUserCompletedEventArgs(false));

 

            // Assert

            Assert.IsFalse(this.viewModel.IsLoggingIn);

        }

 

        [Test]

        public void Login_AfterCompleted_RaisesCanExecuteChangedEvent()

        {

            // Arrange

            bool canExecuteChangedCalled = false;

            this.viewModel.Login.CanExecuteChanged +=

                delegate { canExecuteChangedCalled = true; };

 

            // Act

            this.dataProviderStub.RaiseValidateUserCompleted(new ValidateUserCompletedEventArgs(false));

 

            // Assert

            Assert.IsTrue(canExecuteChangedCalled);

        }

 

        [Test]

        public void Login_WhilstLoggingIn_CannotExecute()

        {

            // Arrange

            this.viewModel.User.Username = "abc";

            this.viewModel.User.Password = "abc";

            this.viewModel.IsLoggingIn = true;

 

            // Assert

            Assert.IsFalse(this.viewModel.Login.CanExecute(null));

        }

 

        [Test]

        public void Login_Always_CallsValidateUserOnDataProvider_WithCorrectUser()

        {

            // Arrange

            User userSentToDataProvider = null;

            this.dataProviderStub.ValidateUser +=

                u => userSentToDataProvider = u;

 

            // Act

            this.viewModel.Login.Execute(null);

 

            // Assert

            Assert.AreEqual(this.viewModel.User, userSentToDataProvider);

        }

 

        [Test]

        public void Login_WithInvalidDetails_CallsLoginUnsuccessfulOnView()

        {

            // Arrange

            this.dataProviderStub.ValidateUser +=

                u => this.dataProviderStub.RaiseValidateUserCompleted(new ValidateUserCompletedEventArgs(false));

            bool loginUnsuccessfulCalledOnView = false;

            this.loginViewStub.LoginUnsuccessful +=

                () => loginUnsuccessfulCalledOnView = true;

 

            // Act

            this.viewModel.Login.Execute(null);

 

            // Assert

            Assert.IsTrue(loginUnsuccessfulCalledOnView);

        }

 

        [Test]

        public void Login_WithValidDetails_SetsFriendListViewOnShell()

        {

            // Arrange

            this.dataProviderStub.ValidateUser +=

                u => this.dataProviderStub.RaiseValidateUserCompleted(new ValidateUserCompletedEventArgs(true));

 

            // Act

            this.viewModel.Login.Execute(null);

 

            // Assert

            Assert.AreEqual(this.friendListStub, this.shellStub.View);

        }

 

        [Test]

        public void Login_WithValidDetails_SetsUserOnShell()

        {

            // Arrange

            this.dataProviderStub.ValidateUser +=

                u => this.dataProviderStub.RaiseValidateUserCompleted(new ValidateUserCompletedEventArgs(true));

 

            // Act

            this.viewModel.Login.Execute(null);

 

            // Assert

            Assert.AreEqual(this.viewModel.User, this.shellStub.User);

        }

 

        [Test]

        public void Register_Always_SetsRegisterViewOnShell()

        {

            // Act

            this.viewModel.Register.Execute(null);

 

            // Assert

            Assert.AreEqual(this.registerStub, this.shellStub.View);           

        }

    }

}


And here you can see them running in the Resharper test runner - they all pass!



Now I can confidently pass my ViewModel to my designer to build a view against...

Or can I? Without a data provider, he's going to have problems creating and testing his view. This will be the subject of the next post.

Sunday, 18 May 2008

MVC Architecting Silverlight Applications Part 2 - Building a ViewModel

In Part 1 of this series I talked about and described the Model-View-ViewModel (MVVM) pattern.

In this post I will describe the application I wish to build to demonstrate this pattern to you, and at the same time demonstrate usage of the Silverstone framework.

A "social networking" application


In picking my sample app I wanted to choose something fairly simple. I decided on a small social networking app, which would basically allow the following use cases:
  1. Register - A user can enter their email address and choose a password. The user must confirm their password. Password must be between 4 and 10 characters. After registering, the user proceeds to use case 3

  2. Login - An existing user can enter their email address and password to login. If they enter the wrong details the system should inform them that their details were incorrect. After logging in, the user proceeds to use case 3

  3. View Friends - Displays a list of friends for the currently logged in user.
And that's it! Despite being fairly minimal (and not that useful without being able to add friends or contact them!) that's all I am going to build for now I think.

Creating a solution


We will name this application "Silversocial" (not very imaginative I know, but it's only a demo app!)

You will require Visual Studio 2008, the Silverlight Tools for Visual Studio, and a copy of Silverstone.dll.

Start off by creating a new project of type Silverlight Application named Silversocial.Client.Views. Choose to create a new solution and call it Silversocial



Choose to add a new Web to the solution for hosting the Silverlight content, and call it Silversocial_WebHost (I choose a web application because I prefer them). The solution will be created containing a Silverlight project and a Web application project.



Out of interest, if you right click on the Web Application project properties, you will see a new tab called "Silverlight links" and you will see that the Silverlight application you just created has been added for you automatically. All this really means is that when you build the Silverlight application, the compiled .xap file will be copied into the Web application's /ClientBin folder.



The shell


The shell in a Silverstone application is the central view component which is responsible for managing the other views in the application. Hence, the IShell interface contains just one method:

void SetView(IView view)

Typically an application will implement the shell as the main UI component containing any navigation and common elements for every page (much like ASP.NET's master page). The application will create its own derived IShell interface and expose any elements required by the individual pages through that interface.

So, given the requirements specified earlier, our application's shell only requires an extra property - the currently logged in User. This would allow the shell's view to display the user and allow the other pages to retrieve it when necessary.

To begin, we will create another Silverlight class project called Silversocial.Client.Modules to house the rest of our application's interfaces and concrete implementations. Obviously in a larger application you would consider splitting your code into multiple assemblies grouped by role.

First, the User class which stores the username and password:

using System.ComponentModel;

 

namespace Silversocial.Client.Modules

{

    public class User : INotifyPropertyChanged

    {

        private string username;

        private string password;

 

        public event PropertyChangedEventHandler PropertyChanged = (s,p) => {};

 

        public string Username

        {

            get { return this.username; }

            set

            {

                this.username = value;

                this.PropertyChanged(this, new PropertyChangedEventArgs("Username"));

            }

        }

 

        public string Password

        {

            get { return this.password; }

            set

            {

                this.password = value;

                this.PropertyChanged(this, new PropertyChangedEventArgs("Password"));

            }

        }

    }

}


And now the shell interface itself:

using Silverstone;

 

namespace Silversocial.Client.Modules

{

    public interface IAppShell : IShell

    {

        User User { get; set; }

    }

}


Creating the first ViewModel


For now, we will not worry about building a concrete View. Instead, we will start with our ViewModel. The page we will build is the Login page, and we will create a new class called LoginViewModel for it.

ILoginView will be the interface which our View will have to implement, and has a single method as follows:

using Silverstone;

 

namespace Silversocial.Client.ViewModels

{

    public interface ILoginView : IView

    {

        void LoginUnsuccessful();

    }

}


The contract states that the LoginUnsuccessful() method will be called by the ViewModel if the login is unsuccessful.

On the other side of the equation, our ViewModel will require some way of actually validating the user. In the real world application we will expose a service for doing this, but for now, let's stub it out with the following interface:

using System;

 

namespace Silversocial.Client.Modules

{

    public class ValidateUserCompletedEventArgs : EventArgs

    {

        public ValidateUserCompletedEventArgs(bool successful)

        {

            this.Successful = successful;

        }

 

        public bool Successful { get; set; }

    }

 

    public interface ILoginDataProvider

    {

        event EventHandler<ValidateUserCompletedEventArgs> ValidateUserCompleted;

        void ValidateUser(User user);

    }

}


(Note that this interface is implementing an asynchronous pattern - raising the ValidateUserCompleted event when the method has completed. This ties in well with the fact that Ajax requests are asynchronous, and that Silverlight's WCF ChannelFactory implementation only supports asynchronous requests.)

The View Model is shown below. The main features are:
  • All dependencies passed through as interfaces to the constructor. This includes other views, the data provider, and the shell.

  • Property exposed for the User, which the View can bind to.

  • Property exposed for whether we are in the middle of a login attempt, which the View can bind to.

  • Exposes a Login command which will attempt to use the data provider to validate the user. If successful the callback will set the user on the shell and change to the FriendListView. If unsuccessful the callback will call the LoginUnsuccessful() method on the view.

  • Exposes a Register command which will simply change views to the RegisterView.

using Silverstone;

 

namespace Silversocial.Client.Modules

{

    /// <summary>

    ///    ViewModel for the login page

    /// </summary>

    public class LoginViewModel : ViewModelBase<ILoginView>

    {

        // Dependencies

        private readonly IAppShell shell;

        private readonly ILoginDataProvider dataProvider;

        private readonly IFriendListView friendListView; // This is just an empty view interface for now

        private readonly IRegisterView registerView; // This is just an empty view interface for now

 

        // Commands

        private readonly ICommand login;

        private readonly ICommand register;

 

        // Data Fields

        private readonly User user = new User();

        private bool isLoggingIn;

 

        public LoginViewModel(IAppShell shell, ILoginDataProvider dataProvider, IFriendListView gameChooserView, IRegisterView registerView)

        {

            this.shell = shell;

            this.registerView = registerView;

            this.friendListView = gameChooserView;

            this.dataProvider = dataProvider;

            this.login = new LoginCommand(this);

            this.register = new RegisterCommand(this);

        }

 

        /// <summary>

        ///    Gets the user being logged in

        /// </summary>

        public User User

        {

            get { return this.user; }

        }

 

        /// <summary>

        ///    Gets or sets whether the user is currently being logged in

        /// </summary>

        public bool IsLoggingIn

        {

            get { return isLoggingIn; }

            set

            {

                isLoggingIn = value;

                this.RaisePropertyChanged("IsLoggingIn");

            }

        }

 

        /// <summary>

        ///    Gets the command used to login the user

        /// </summary>

        public ICommand Login

        {

            get { return this.login; }

        }

 

        /// <summary>

        ///    Gets the command used to register a new user

        /// </summary>

        public ICommand Register

        {

            get { return register; }

        }

 

        private class LoginCommand : CommandBase<LoginViewModel>

        {

            public LoginCommand(LoginViewModel viewModel) : base(viewModel)

            {

                this.ViewModel.dataProvider.ValidateUserCompleted += this.HandleValidateUserCompleted;

            }

 

            public override bool CanExecute(object parameter)

            {

                // Used to inform the command framework that we can only login once the user

                // has entered a username and password and we are not already in the middle of a login

                return !string.IsNullOrEmpty(this.ViewModel.User.Username)

                    && !string.IsNullOrEmpty(this.ViewModel.User.Password)

                    && !this.ViewModel.IsLoggingIn;

            }

 

            public override void Execute(object parameter)

            {

                // Call the Async method on the data provider to validate the user.  The ViewModel will

                // handle the response to this method

                this.ViewModel.dataProvider.ValidateUser(this.ViewModel.User);

 

                // Record that we are currently in the middle of a login attempt

                this.ViewModel.IsLoggingIn = true;

            }

 

            private void HandleValidateUserCompleted(object sender, ValidateUserCompletedEventArgs e)

            {

                // Record that we have finished attempting to log in

                this.ViewModel.IsLoggingIn = false;

 

                if (e.Successful)

                {

                    this.ViewModel.shell.User = this.ViewModel.User;

                    this.ViewModel.shell.SetView(this.ViewModel.friendListView);

                }

                else

                {

                    this.ViewModel.View.LoginUnsuccessful();

                }

 

                // Raise the "CanExecuteChanged" method

                this.RaiseCanExecuteChanged();

            }

 

        }

 

        private class RegisterCommand : CommandBase<LoginViewModel>

        {

            public RegisterCommand(LoginViewModel viewModel) : base(viewModel)

            {

            }

 

            public override void Execute(object parameter)

            {

                // Simply use the shell to navigate to the register view when this command is executed

                this.ViewModel.shell.SetView(this.ViewModel.registerView);

            }

        }

    }

}

The next post

In the next post I will talk about unit testing the view model, and will start to wire things together so our designer can build a View for all this.

Tuesday, 13 May 2008

TestDriven.NET adds NUnit support for running Silverlight tests

This is great news from Jamie Cansdale - Silverlight NUnit Projects

He has managed to get a plugin working for NUnit which will run tests compiled for Silverlight directly!

I was previously using the "in-browser" testing framework provided by Jeff Wilcox. As great as this is, it's always nice to be able to run tests directly from the IDE, and this will finally provide it for Silverlight.

So... it looks like I'm going to have to update my Silverlight samples (which I am in the middle of writing) to use this new plugin. These are taking longer than expected but will definitely be published soon - and hopefully before I have to update them again for SL Beta 2!

Oh - and it even works with the Resharper test runner!

Good work Jamie!

Saturday, 3 May 2008

Silverlight 2 - Creating bindings between FrameworkElements using Silverstone

I spent an evening last week working on some code for my Silverstone framework which would allow you to bind a property on an element in XAML to a property on another element. This is something which you can do very easily in WPF, using the {Binding ElementName=xxx} markup extension, but is not currently possible in the Beta 1 version of Silverlight 2.

The syntax I wanted to achieve would be something like this:

<Silverstone:ElementNameBinding Target="textBlock" TargetPropertyName="Text" Source="textBox" SourcePropertyName="Text" />
Essentially I would create a separate control which would bind the text of a source TextBox to the text of a target TextBlock called within the same UserControl (although obviously this can be used with any arbitrary property). The idea to demonstrate this is that when the user changes the text of the TextBox, the text of a TextBlock on the page would reflect what he is typing.

I got as far as getting the code working, so the text was initially populated into the target TextBlock. I did this by creating a Binding between the properties using a bit of reflection combined with the existing SetBinding() method. However, the binding was not picking up any changes! This is because the BindingExpression implementation in Siverlight does not expect the binding source to be a DependencyProperty but rather it expects to find an implementation of INotifyPropertyChanged.

So I continued, trying to manually find the DependencyProperty which was being sourced and adding a listener to its change event. However there is no way to do this in Silverlight! Thinking in WPF terms, I was expecting to be able to grab hold of the metadata for the dependency property and add a handler through that, or alternatively to instantiate a DependencyPropertyDescriptor and calling the AddValueChanged() method.

Neither of these exist in Silverlight 2 Beta 1, so I started playing around in Reflector and trying to manually attach to it, something along the lines of:

DependencyProperty boundProperty = (DependencyProperty)
    propertyType.GetField(this.PropertyName + "Property").GetValue(target);

PropertyChangedCallback propertyChangedCallback = (PropertyChangedCallback)
    boundProperty.GetType().GetField("_propertyChangedCallback", 
        BindingFlags.NonPublic | BindingFlags.Instance)
    .GetValue(boundProperty);

Unfortunately, I ran into the good old Security exception - turns out all this code I was trying to access is marked with the SecurityCriticalAttribute which means you can't access it through reflection.

I pretty much gave up at this point. Begrudgingly I closed my laptop, kissed my girlfriend goodnight and drifted to sleep whilst trying to think of an alternative...

Well a week has gone by now and I thought I'd write this blog article to describe what I'd tried, in case anyone else wanted to try the same thing. It was only when describing my problem that I realised I had been leading myself completely in the wrong direction with my attempts. I could easily utilise the existing binding framework to do the job for me!

All I would need to do is create a "surrogate property" on the binder, create a two-way binding from the source to the surrogate property, and another one-way binding from the surrogate property to the target. By implementing the INotifyPropertyChanged interface on the binder control, I could notify the target whenever the source had changed it would automatically re-read the value. It worked a treat and was so simple!

I think the old saying "if at first you dont succeed..." is very appropriate here. I would also consider the relevance of the "go home and sleep on it" phrase. How many times do you work on problem for an entire day but to no avail, then go home and when come back in the next morning you have the problem solved even before your morning cup of tea!

Anyway, the class Silverstone.ElementNameBinder has been updated now supports this. It is available as of version 0.1 of Silverstone.dll. Get it here or get the source code from the svn repository. If anyone decides to use it and has any questions, of course please let me know.

Have a great day!

Neil

Friday, 2 May 2008

Silverlight 2 - Configuration Files are not picked up

I just saw this post on Mike Taulty's blog about the MaxMessageReceivedSize config setting not working in Silverlight 2's config file.

Mike's solution was to set the property in code but he wasn't sure why he had to do this.

This is happening because the config file is actually never read by Silverlight. It's generated when you add the Service Reference, but it's never picked up. I don't know why it's created actually, it only serves to confuse people! Maybe it will work in a future version... but if you look in the generated Reference.cs of the ImageServiceClient, you will see that the default constructor of the proxy sets the binding to BasicHttpBinding and sets the appropriate Url, essentially mirroring what is in the config file.

Silverlight currently does not have any support for configuration files (there is no System.Configuration namespace at all!). If you wish to configure your Silverlight components, I could suggest that you just use XAML... alternatively you could pass XML through a hidden form field which the Silverlight application reads. The point is that whatever you do will be completely custom.

Anyway I hope this helps someone out there who is wondering why his config changes aren't working.

Tuesday, 22 April 2008

MVC Architecting Silverlight Applications Part 1 - M-V-VM

In my previous post I mentioned that I had used the Model-View-ViewModel approach to building WPF applications.

In this series of blog posts I will describe this pattern, and show you how to build a small sample application using it within the context of Silverlight. I have folded a bunch of base classes and helper classes into my open source Silverstone framework and these will be used extensively.

What is Model-View-ViewModel

I am assuming that those of you reading this post are familiar with the Model View Controller pattern and have probably used it in some form of ASP.NET or WinForms application. If not then you might want to check out Martin Fowler's article on GUI Architectures for an in depth technical appraisal, or this page on the MSDN site for more information.

The Model-View-ViewModel (or MVVM) pattern is a form of MVC specifically catered for scenarios where you have a very strong data binding ability within the framework, and also one where you want to give your designers the freedom to design the view completely themselves.

Let's explain the three components now:

Model - The Models are the classes which represent the domain on which the application is processing/interacting with. I often refer to these as DataModels, as they are modelling the data in the application, and usually contain some kind of business rules and validation logic.

View - The Views are simply the classes which the render the graphical elements to the user and allow him to interact with the application. They are ideally implemented in 100% markup, although in practise there will end up being some code there too!

ViewModel - The ViewModels are the new kids in town for those of you familiar with traditional MVC/MVP. They essentially take the part of the controller or presenter, and are named as such because they "model the view". Each ViewModel is therefore built for a specific View, and contains all the data and behaviour logic which that View requires to interact with the data models.

Why "ViewModel"?

In an MVC application, the Controller will typically respond to an event when notified by the view, such as a "Save" button being clicked. It will usually then interact with the model in some way, e.g. reading some values from the view and applying them to the model. Finally it will notify the view of something. For example, it may tell it to display a "your model was saved" message to the user, or alternatively to display a validation warning if something went wrong.

The ViewModel has the same responsibility as the controller, but it handles that responsibility in a different way. Firstly, it makes use of the rich binding provided by the platform by exposing data to the View and raising property changed notifications when that data changes. It also expects the view to use two way binding to push changes direcly back to those properties. Only the data which is required for that specific view is exposed. This will generally include the models which the user needs to view or edit as well as controlling properties which tell the view which state it is in. For example the ViewModel may expose a boolean property which tells the view that it is in the process of saving the DataModel.

At the same time, the ViewModel exposes Commands for the View to execute. It does so in such a way that the commands can be bound directly to UI elements (such as buttons). It is the commands which are responsible for handling user interactions. For example , a save command may be exposed which saves whichever changes users have made to the data models. See my previous blog post for more information on Commands in Silverlight

In Silverlight and WPF terms, the important point to take home is that the ViewModel is the DataContext of the View. This is the key enabler of all the data binding I have been referring to!

And that's really it for now. I hope this makes sense a summary for the architecture pattern we are trying to follow. If you have any questions please let me know.

In the next part of this series, I will begin walking through how to develop a small application using this pattern under Silverlight.

Have a great day!

Neil

Sunday, 13 April 2008

A basic IoC container for Silverlight

All the recent User Interfaces I have built have been developed using some kind of MVC approach - be it the good old MVP (Model/View/Presenter) pattern for WebForms applications, or the recently devised MVVM (Model/View/ViewModel) pattern for WPF.

Well I recently started work on a small "pet project" using Silverlight (let's just assume for those who know me that the aforementioned pet is a Horse) and some of my development seems to have been spent building shared components which could be used in other projects. For example, I have previously blogged about my Command Implementation for Silverlight which I am using in this project.

When building MVC applications, a key piece of the developer's strategy is the ability to abstract a class's dependencies into an external component which will resolve those dependencies at runtime into what is required by the application. This allows (for one thing) the developer to build each class without worrying too much about where that class obtains its dependencies from. Note that classes which resolve other class's dependencies at runtime (a technique known as Dependency Injection) are commonly known as Inversion of Control containers. I won't get into much more detail about this here and recommend reading this excellent MSDN article.

So, despite previous attempts to cross-compile the excellent Ninject IoC framework into Silverlight (see this blog post and comments) I failed to get it to run. The problem is that Silverlight implements a new security model, in which lots of framework methods (such as some of System.Reflection.Emit, and System.Threading.StackTrace) are not allowed to be executed from application code. Essentially, if you look in Reflector at the Silverlight libraries, anything marked with a [SecurityCritical] attribute will be inaccessible to any code you write. If you are interested, you can get more information about Silverlight's new security model here. Personally, I think it's a little overzealous, and I hope the restriction will be lifted somewhat as Silverlight's deployment mechanism matures - I'm not sure how it would work but I'd like to see shared libraries being built which are able to call into some of the code deemed critical. I guess that's not my call though!

Anyway, given that no container I could find out there would run on Silverlight, I set about writing my own IoC container to "free myself" from my dependencies, so to speak. I pushed my code into a small library I have named Silverstone. You can download the DLL here.

The container is implemented as a very simple static class - Silverstone.DI.IocContainer. What I am currently doing is just registering all my dependencies in the Startup method of my App.xaml.cs, as follows:

using Silverstone.DI;

public partial class App : Application
{
  public void Application_Startup(object sender, StartupEventArgs e)
  {
    // Register an instance of a concrete type MyClass against interface IMyInterface.
    // The instance will be passed to all constructors with parameter of type
    // IMyInterface and all settable properties of type IMyInterface.
    IocContainer.RegisterInstance<IMyInterface>(new MyClass());

    // Register a concrete type against an abstract type.  This means that a new
    // instance of the concrete type will be created every time the abstract type is
    // requested by either a constructor with parameter of type IMyInterface or a
    // settable property of type IMyInterface.
    IocContainer.RegisterForCreation<MyClass, IMyInterface>();
  }
}

That's pretty simple really! Note that you can only register the same abstract type (IMyInterface in this example) once.

When you wish to retrieve the implementation of any abstract type, it's just a simple call to Get<>();

  IocContainer.Get<IMyInterface>();

Assuming that MyClass had been registered against IMyInterface in the container, the above call would actually return an instance of MyClass. Otherwise it will return null.

That's all there is to it really! Of course, the container is iterative and will walk the tree of constructors and properties on all objects as it goes. So, for example, if MyClass has a constructor with a parameter of type IMyOtherInterface, that will be requested from the container when creating the instance of MyClass. This is where the power of a container comes in - when you don't have think about all the dependencies of the dependencies of your dependencies, you can think a lot more clearly!

If anyone starts using this stuff and has any feedback, please let me know. Alternatively you can take a look at the source code which is available on the Google Code site for the project.

Have a great day

Neil