Zero Gravity C#imp

Misconceptions about MVVM

clock November 20, 2011 15:33 by author ZeroGravityChimp

Greetings readers. This post covers some basic concepts and application principle behind MVVM pattern.

I’m assuming you have some basic knowledge of what the MVVM pattern contains, for example you should know

  • ·         What a view is (UserControl)
  • ·         What a ViewModel is (inherits DependencyObject and acts as the datacontext for the view)
  • ·         What an ICommand is (a delegate that can be bound to via the XAML)

Etc.

My interpretation of the pattern is that the code should follow these principles:

  • 1.       No Code-Behind (xaml.cs) file
  • 2.       Separation of concern
  • 3.       Decoupling of objects.

Let’s explore these principles

1.       No Code Behind

This is a simple idea, that all of the properties and functions that need to be exposed to the view can be pre-calculated and presented to the view in the DataContext. The view needs to make absolutely no decisions at runtime.

Where some logic is completely view specific, for example converting a string “blue” into a SolidColorBrush, you should use a converter.

There are rare cases when a control only supports some type of function in codebehind. In these cases you should implement the codebehind, but you should also ask yourself why DataBinding is not supported, since the entire Silverlight Toolkit and many other controls do support this out-of-the-box. In some cases, you may even find instructions on creating an MVVM-friendly version of the control.

2.       Separation of Concern

The ViewModel should:

·         Get Data from the service layer, model layer, or data source

·         Rework the data into any type of custom object that is needed for the final presentation

·         Filter or reorder the data down to the relevant set for viewing

·         Provide every integration point for user interaction as a Command

·         Populate DependencyProperty attributes so that they can be bound to.

The View Should:

·         Use DataBinding to display the data from the ViewModel

·         Use Converters, if necessary, to convert properties to View-Specific types.

·         As shown above, the properties supplied and/or requested may not be a 100% match, but this would not inhibit the controls from operating correctly as implemented.

3.       Decoupling of Objects

The ViewModel should not:

·         Access any properties of any of the View’s Controls or components or the View itself

·         Call any methods that are defined in the View’s Controls or components or the View itself

·         Throw an error if something in the View has changed (Build Error or Runtime Error)

The View Should Not:

·         Throw an error if something in the ViewModel has changed (Build Error or Runtime Error)

Resist the urge to get a reference to your Sender in the Commands!

Until next time,

Chimp

 

 



Unit Testing for Silverlight in Visual Studio

clock September 17, 2011 16:52 by author ZeroGravityChimp

Most people don't know that you can use the .Net Unit Testing studio for your Silverlight functions! This includes the ability to run tests without a web server. In fact, you don't even need to run the silverlight in a browser to see the test results. If that's not enough, your test results will also be able to integrate with Studio and even TFS Team Build if you need them to. Sound good? Read on...

Quick note, I apologise for my long absence since we've had a recent edition to my family. Hopefully I can contribute some pointers over the next few months.

To demonstrate how to set up unit testing I have created a Silverlight project called "SilverlightTestedApp" and a corresponding SilverlightTestedApp.Web project to host it using Visual Studio 2010 (I'm doing this demo using Silverlight 4.0 In-browser but out of browser and other versions should all work fine).



I am going to go ahead and modify the project to hold 2 basic TextBox elements for input and a TextBlock element to show the output. We are going to display the output based on user input, so I have added the following code and event handlers:



When I run the project I can see the output as a combination of the 2 input fields. I have simulated a common UI scenario where the client-side front-end is required to make a decision and modify the data so that it can be displayed without locking up the UI. In this case, the text components should not exceed 20 characters. If they do, take the first 17 and append an ellipse ("...") to the end of that component. The 2 components are shown side by side in the output text box separated by a semicolon.



In order to do a unit test on this project, I would first want to refactor my code into 1 method. The following section is an example of how the code could be simplified and made reusable:



Now we can use this method throughout the class to convert any string to a Display Name (max 20 characters) using our conversion algorithm. It is simple, but functional. You may think that this method is too simple to unit test but I will show you how easily it can fail. Let's get started writing some unit tests...

I'm going to create 2 projects: AppFunctions and AppFunctions.Silverlight. AppFunctions will hold our functions, and this project should be of type .Net Class Library (Not Silverlight!).

scr5

I am next going to add the AppFunctions.Silverlight project. This should be a Silverlight class library. My IDE also asked me the version, which I specified as Silverlight 4.0.



Your solution now contains 4 projects. The source code we write is required to build twice. It should build once as a .Net 4.0 Class Library for unit tests and once as a Silverlight Class Library for the runtime app. To set this up, put the methods you want to test in the .Net project. In my case I have a new code file called "NameFunctions" with the GetDisplayName method inside (I also deleted the "Class1.cs" files that were created by default.) as shown:



Note that the class and method are made public. The next step is to right click your AppFunctions.Silverlight project, click "Add" -> "Existing Item" and browse to the NameFunctions.cs file. When you have selected the file do not click "Add". Instead, click the arrow on the right of the "Add" button and select "Add As Link".



We also need to wire this up to the Silverlight App. Right click the original project, click "Add Reference" and choose the "Projects" tab in the dialog. Then choose the AppFunctions.Silverlight project. In the code file you must add a Using reference to the AppFunctions namespace and create a NameFunctions object as shown: Finally, use this object to invoke the method you need to call.



This could be done using static methods as well, and I don't see any problem with that. Build your solution and confirm that the stack is functioning as it was before we moved the code to a different project.

Time to recap:

What are we attempting to do:
   *  Separate logical methods into a different assembly
   *  Link the assembly so that it can be used in silverlight, but tested in .Net
   *  Write and perform tests using Visual Studio

All that's left to do now is the Unit Tests. To do this, right click your solution and click "Add New Project". In the dialog, select the "Test" grouping and select "Test Project". I have named mine AppFunctions.Test.



Next, Right Click the Test Project and select Add -> New Test to create a unit test. Your test project requires reference to the assembly you want to test. In my case I have added a project reference to "AppFunctions" and referenced it to write the following test class:

namespace AppFunctions.Test
{
    [TestClass]
    public class NameFunctionsTest
    {
        [TestMethod]
        public void GetDisplayNameNullTest()
        {
            NameFunctions funcProvider = new NameFunctions();
            string output = funcProvider.GetDisplayName(null);
            Assert.AreEqual(output, null);
        }

        [TestMethod]
        public void GetDisplayNameShortTest()
        {
            NameFunctions funcProvider = new NameFunctions();
            string testString = "abc";
            string output = funcProvider.GetDisplayName(testString);
            Assert.AreEqual(testString, output);
        }

        [TestMethod]
        public void GetDisplayNameLongTest()
        {
            NameFunctions funcProvider = new NameFunctions();
            string output = funcProvider.GetDisplayName("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
            Assert.AreEqual(20, output.Length);
        }

        [TestMethod]
        public void GetDisplayNameFormatTest()
        {
            NameFunctions funcProvider = new NameFunctions();
            string output = funcProvider.GetDisplayName("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
            Assert.IsTrue(output.EndsWith("..."));
        }
    }
}

Remember to build the solution to make sure no errors have been introduced. Now that the tests are written, running them in the IDE is quite easy. My preference is to go to Test -> Windows -> Test View



If the project has been built you can run the tests straight away in the test view by selecting the names of the tests and pressing the "Run" button.



I have intentionally created a test that will fail! passing Null into my method would causes an exception. Now by simply changing the basic function we can make this test pass. Below is a sample of improving a basic string function to cater for a null parameter value:

        public string GetDisplayName(string textInput)
        {
            string result = null;
            if (textInput != null)
            {
                if (textInput.Length < 20)
                    result = textInput;
                else result = textInput.Substring(0, 17) + "...";
            }
            return result;
        }

This will cause the GetDisplayNameNullTest to pass!

I hope that these simple examples will help someone to set up a few unit tests for their code and hopefully improve their whole Silverlight solution.

Happy coding!

Zero Gravity Chimp



Is Silverlight going to be replaced by HTML5.0?

clock November 13, 2010 11:36 by author ZeroGravityChimp

Some people have heard about the Conference where Microsoft showed their 3 screen ideal linked together using HTML 5.0.

Last year at this same event the screens were brought together with Silverlight. So this has caused a lot of hype. Is Silverlight being canned for HTML 5.0? I think not.

I think it's a miscommunication.

HTML5.0 is cross-platform. that is the point. Some people will have heard that Silverlight is supposed to be cross-platform too but they've since said that it would be impossible to have a plugin working on every single platform with the amount of devices now available to consumers. They still plan to have it working on Windows and Mac and as the software platform for Windows Phone 7.0

Silverlight is an extension for web that allows us to do custom functions based on their framework (which is a subset of .Net).

I don't believe a framework like .Net (or the JavaFx or ActionScript-based equivalents) can be replaced by a web convention such as HTML 5.0.
Any function or library in HTML5.0 would have to be supported by EVERY browser and EVERY phone. These functions need to be generic such that all web developers accross the sphere can use them.

Think about Javascript and HTML as is... The world does not use those in a uniform fashion and I don't believe they really can because that is the nature of scripts and languages.

As soon as we wish our language to be custom up to a certain point - that is, we decided that this particular code library is good enough to be packaged and distributed as a framework - we have a situation. Some frameworks aim to make everything possible using the convention such as JQuery but other frameworks are built on disparate foundations - like .Net and Java reject the web browser capability to offer a richer capability that plays through a plugin.

That is why silverlight currently exists. We want all the fancy IDE's, build tools, .Net, and all of that that has gone into it. We can't have exactly that with HTML - so there is a plugin. The bonus is that is becomes extendable. Silverlight uses TFS integration, Visual Studio 2010, Blend and other tools from Expression Studio by Microsoft. These tools have different uses and merits and are different from provider to provider. That is the great environment that RIA is giving developers.

I believe that as long as there will be third party frameworks, including the Adobe ones, the .Net and the Javas of the world, there will be framework-based RIA for web. And I'm quite certain that frameworks as a concept are here to stay.

Having said that, the size of that market for these may well change. I believe the market for Silverlight will increase as long as Microsoft and their partners can explain clearly to people: This is a way that people in my organisation or your organisation can produce software that works, works well, works easily, works on many platforms... Those benefits will still be true for silverlight 10, 11, 12 and onwards.

It is for these reasons that I think there is, and will continue to be, a line in the sand between plug-ins for RIA and base-line conventions for HTML support in browsers accross the globe.

Now all we need is for Silverlight to support Linux, Android, and all the Apple devices :(

Regards