I must say, I really like the MVVM pattern for doing both Silverlight and WPF development. I have been using it for quite some time now, with and without a standard framework. And although I really like the pattern, I have also seen some bad code pop-up in applications that are more like anti-MVVM. The reason for this is that the responsibilities of each part of the MVVM pattern get mixed up. People seem to think that once their class has the 'ViewModel' extension it actually behaves like a viewmodel, which is not always the case.
For starters, I have seen people use MVVM without the first M. That is, people tend to do MVVM without a model and just put everything in their viewmodel, even their model data. It pops up like private data members in the viewmodel, where they actually should use a model. The temptation for doing this can be quite big, since often you have to put propertychanged notifications in your viewmodel. It just seems that much easier to skip the model for this. The temptation seems to be biggest in applications where there is no real back-end, like a service, that needs to be called, that hands you off something model-ish.
Another sin in MVVM applications is the over-use of the commands in a viewmodel. They are there as a hook for your view to tell the viewmodel to 'do something' or that 'something needs to be processed'. This doesn't mean that all of the logic for the something that needs to be done, has to be put in the viewmodel. It is ok for the viewmodel to ask some other component to handle the details of the something that needs to be done. For this, keep the rule of single responsibility in mind. The moment your viewmodel starts to do more than what it's supposed to do, you probably need to refactor out some of the logic (maybe hand it of to the model or to some other component).
Your viewmodel should only have the logic for bridging between your view and your model. It is there to present the data of the model in such a way so that it makes sense to the view. And it also contains commands so that the view can interact with the model. And that is all it should do. This also implies that the model can be (even has to be) more than just a POCO or DTO, it can contain logic if it needs to. This is often a misconception in MVVM, where the model is seen as just a class that contains data. But this is often not the case. Often, the model is a back-end, which contains business logic and which hands you off POCO or DTO classes. Often it is more than just one model class, it can be a whole bunch of classes, all interacting to provide your viewmodel with services.
A last offense can be found in the view. It is still ok to put logic in the xaml.cs file, but make sure you limit this to view-specific logic. That is, for instance, the logic that is needed for a certain animation to display properly. And that's all. All of the other logic should be in your viewmodel or should be delegated from your viewmodel to other components. So don't start putting state specific logic in the code behind of the view. This means that, if you have animation specific code in your code behind, the actual check 'IsAnimating' should be in your viewmodel.
That's the end of my MVVM pattern rant. I really really like this pattern, but just keep in mind that it is not because you use a certain pattern, your code keeps to it. Keep the different responsibilities of each part of the pattern in mind, so you don't accidentally mix them up.
Showing posts with label Silverlight. Show all posts
Showing posts with label Silverlight. Show all posts
Saturday, September 17, 2011
Some MVVM Badness
Tuesday, April 19, 2011
Windows Phone 7 Course
A couple of weeks ago I followed a two day Windows Phone 7 course (a little thank you to Microsoft for making this course free for Microsoft Partners is in place here). During the course, there were some small issues mentioned you need to take into account when developing for a Windows Phone 7 device that don't seem so obvious. Just to get you started, here's an overview of the most important stuff that's different from regular Silverlight development. I won't go into the gory details, just give you an overview of some stuff that I thought was a bit peculiar or different to what I was used to and some stuff you just need to know, which you don't find easily on the MSDN site.
First of all, when doing Windows Phone 7 development, you can use an emulator to see the result of all your hard coding work. That is, if you don't have the real stuff (which I don't, all donations are welcome!). When working with the emulator, one of the time consuming tasks, is typing in characters (eg. when editing a text box). The emulator gives you an on screen keyboard you can use to type, but this is not very practical when using your mouse! And if you try using your pc's keyboard to type, you'll find your key presses are not accepted.
There is, however a very quick and easy solution to use your pc's keyboard: just press your pause button (you know, the one you hardly ever use) and start to type. Once you're done typing, just press pause again. This will save you loads of time in the emulator.
Next, if you want to use animations in your Silverlight application, there are several ways to start a storyboard. You can do this with an event trigger in your XAML, using code, or by using the visual state manager. When developing for a Windows Phone 7 however, be aware that when using event triggers in XAML, only the Loaded event is available. Because you have this restriction, the better option to start a storyboard animation is by using code, just because it gives you more options.
Another difference is the absence of the NotifyOnException and NotifyOnValidation options you normally have for Silverlight databindings. These are just not there. If you get an error on your databinding, keep in mind, you will not see this in your interface.
If you want to unit test your Windows Phone 7 application you're out of luck. The standard unit test project type of Visual Studio is not compatible with the Windows Phone 7 project type. I am pretty sure however it must be possible to unit test your app using a 'plain old' NUnit class library (which I still think is a better option than the build in unit testing Visual Studio gives you).
One last, very small tip: don't close your emulator each time you change something in your code. It just increases the start-up time when you run your app. It's not a big thing, but it can truly save you a lot of time.
So, there you have it, some small, but still important things to keep in mind when developing for a Windows Phone 7 device. One of my next private projects will be a small 2D and 3D XNA app for the Windows Phone 7 (after teaching OpenGL and XNA a couple of years, I'm just aching to try this). I promise I will make some posts about it. And at this moment at QFrame (my company) we are also working on an (almost finished) Silverlight app for the phone, which uses Azure services and which we will demo at the Belgian TechDays 2011 next week. Be there!
First of all, when doing Windows Phone 7 development, you can use an emulator to see the result of all your hard coding work. That is, if you don't have the real stuff (which I don't, all donations are welcome!). When working with the emulator, one of the time consuming tasks, is typing in characters (eg. when editing a text box). The emulator gives you an on screen keyboard you can use to type, but this is not very practical when using your mouse! And if you try using your pc's keyboard to type, you'll find your key presses are not accepted.
There is, however a very quick and easy solution to use your pc's keyboard: just press your pause button (you know, the one you hardly ever use) and start to type. Once you're done typing, just press pause again. This will save you loads of time in the emulator.
Next, if you want to use animations in your Silverlight application, there are several ways to start a storyboard. You can do this with an event trigger in your XAML, using code, or by using the visual state manager. When developing for a Windows Phone 7 however, be aware that when using event triggers in XAML, only the Loaded event is available. Because you have this restriction, the better option to start a storyboard animation is by using code, just because it gives you more options.
Another difference is the absence of the NotifyOnException and NotifyOnValidation options you normally have for Silverlight databindings. These are just not there. If you get an error on your databinding, keep in mind, you will not see this in your interface.
If you want to unit test your Windows Phone 7 application you're out of luck. The standard unit test project type of Visual Studio is not compatible with the Windows Phone 7 project type. I am pretty sure however it must be possible to unit test your app using a 'plain old' NUnit class library (which I still think is a better option than the build in unit testing Visual Studio gives you).
One last, very small tip: don't close your emulator each time you change something in your code. It just increases the start-up time when you run your app. It's not a big thing, but it can truly save you a lot of time.
So, there you have it, some small, but still important things to keep in mind when developing for a Windows Phone 7 device. One of my next private projects will be a small 2D and 3D XNA app for the Windows Phone 7 (after teaching OpenGL and XNA a couple of years, I'm just aching to try this). I promise I will make some posts about it. And at this moment at QFrame (my company) we are also working on an (almost finished) Silverlight app for the phone, which uses Azure services and which we will demo at the Belgian TechDays 2011 next week. Be there!
Labels:
QFrame,
Silverlight,
Techdays,
Windows Phone 7,
XNA
Monday, April 4, 2011
Doing the dynamic thing (Part III)
In the first part of this series I gave an introduction to what the dynamic keyword can do for you. The second part of this series showed you how this dynamic keyword can be pretty handy when interoperating with javaScript code. in this third part we will look into interoperating with Excel. This part will be brief, though, mainly because there are already quite a lot of examples to be found concerning this subject.
In this post I will extend the example I started in the previous post. There, we've seen I get a list of Person data from a WCF service. This Person list is shown in a DataGrid control of a Silverlight application. The latest version of Silverlight, supports running out of browser and once you run out of browser you get some extra possibilities for your application. One of these possibilities is interacting with automation objects, like Excel. So, let's extend our example so it can run out of browser and also, so it can generate an Excel document.
Running out of browser is actually not that hard to do. The user of your application can right click on the Silverlight application and choose 'Install NameOfYourApplication onto this computer'.
In this post I will extend the example I started in the previous post. There, we've seen I get a list of Person data from a WCF service. This Person list is shown in a DataGrid control of a Silverlight application. The latest version of Silverlight, supports running out of browser and once you run out of browser you get some extra possibilities for your application. One of these possibilities is interacting with automation objects, like Excel. So, let's extend our example so it can run out of browser and also, so it can generate an Excel document.
Running out of browser is actually not that hard to do. The user of your application can right click on the Silverlight application and choose 'Install NameOfYourApplication onto this computer'.
To offer this right click functionality to your users you need to check the 'Enable running application out of the browser' checkbox in the project settings of your Silverlight application.
The button control under this checkbox will show a popup window with some extra settings. One of these extra settings, 'require elevated trust', is important if you want to offer automation functionalities in your out of browser Silverlight application, so you should check this as well.
Once you have done this, your users can install your application.
In code it is possible to test whether or not you are running out of browser. I, for instance, added some code to disable a button that generates HTML if we are running out of browser, since generating HTML is pretty useless if you're not running in a browser window (and if you do execute the generation of HTML out of browser you will get a runtime error, so better disable it).
btnHTML.IsEnabled = !Application.Current.IsRunningOutOfBrowser;
We can also test whether or not we can use the automation capabilities.
if (AutomationFactory.IsAvailable)
Once we know we have automation available, we can create a new Excel object. The return type of the GetObject and CreateObject calls is dynamic, so this is a good choice for the type of your variable.
dynamic ExcelApp; try { ExcelApp = AutomationFactory.GetObject("Excel.Application"); } catch (Exception exc) { try { ExcelApp = AutomationFactory.CreateObject("Excel.Application"); } catch (Exception exc2) { txtStatus.Text = exc2.Message; return; } }
The reason I use both GetObject and CreateObject is that if Excel is already running, we can get a reference to the application with GetObject. If Excel is not already running, we need to start, or create the application with CreateObject.
Once we have the Excel application at our disposal, we can create workbooks, we can add data to cells, etc. The good news is that, since version 4.0 of the .NET framework all objects in Excel (and in the other Office automation frameworks) are of type dynamic. This simply means you can omit a lot of casting operators. Where previously you needed to write code like this:
var ExcelApp = new Excel.Application(); ExcelApp.Visible = true; Workbook workbook = ExcelApp.Workbooks.Add(); int rowCounter = 1; foreach (DataService.Person p in dataGrid1.ItemsSource) { ((Range)((Worksheet)workbook.Sheets[1]).Cells[rowCounter, 1]).Value = p.FirstName; ((Range)((Worksheet)workbook.Sheets[1]).Cells[rowCounter, 2]).Value = p.LastName; rowCounter++; } ((Range)((Worksheet)workbook.Sheets[1]).Columns[1]).AutoFit(); ((Range)((Worksheet)workbook.Sheets[1]).Columns[2]).AutoFit();
You can now write this much more briefly like this:
ExcelApp.Visible = true; dynamic workbook = ExcelApp.Workbooks.Add(); int rowCounter = 1; foreach (DataService.Person p in dataGrid1.ItemsSource) { workbook.Sheets[1].Cells[rowCounter, 1].Value = p.FirstName; workbook.Sheets[1].Cells[rowCounter, 2].Value = p.LastName; rowCounter++; } workbook.Sheets[1].Columns[1].AutoFit(); workbook.Sheets[1].Columns[2].AutoFit();
As you can see, there is a lot of casting going on in the first example, primarily to the Worksheet type and to the Range type. This is something we can completely omit when using dynamic. Which, in my opinion is a good thing!
The bad news, however, is, that with these dynamic types, your intellisense is gone. You need to know which operation calls are valid on which objects. But than again, who cares, because previously you needed to know which type you needed to cast to. If you got that one wrong, you'd get a runtime exception as well.
If you want to know even more on automation, this article in the MSDN library can give you some extra info.
That's it for the Office automation part of this series. Be ready to do some serious stuff with ExpandoObjects in the next post.
Labels:
.Net,
automation,
C#,
dynamic,
Excel,
Office,
Silverlight
Sunday, April 3, 2011
Doing the dynamic thing (Part II)
After the basic intro given in the first part of this series, it is time for something more advanced. It won’t be rocket science, yet, but you will get more insight into what dynamic coding can do for you.
As mentioned in the previous post, dynamic programming can help you a lot when working with COM objects. I will give an example of this for JavaScript objects in a small Silverlight application. In the next post I will extend this simple example and I will explain interaction with Excel. But first, let’s talk about JavaScript.
Interacting with JavaScript might be something you need in real life. For instance if you have a Silverlight app that is hosted on a page that relies on JQuery a lot. JQuery can provide you with objects your SilverLight application does not know about. How can you interact with these objects if your managed code doesn’t know their type? The answer is to utilize dynamic.
To illustrate this, suppose we have a service running that can give us data about persons. A Person being just a DTO class with a FirstName and LastName property. Plain and simple.
I also have a HTML page that includes a SuperPerson object. A SuperPerson being the same as a Person, but with one extra property, 'somethingextra'.
In this example, to keep it simple, I will build a HTML table. It will be the Silverlight code that builds this table, not the JavaScript code. For this, first thing will be to get hold of a specific div tag on the HTML page in which we will build our table. Silverlight lets you interact with the hosting page through the HtmlPage class. This class gives you a Document property that behaves pretty much the same as the document object in JavaScript, which makes it very easy to use.
A second thing you may have noticed is a second use of the dynamic keyword. When I create a new td element, I do not use the HtmlElement type (which is valid for a td tag), but instead I use the dynamic keyword. I do this because I know for sure it is possible to call the innerHtml operation on a td tag. The HtmlElement, however, does not have this operation present (you can check this in your intellisense). There is also no specific type for a td element that does have this operation present. With dynamic there is no problem at all to call innerHtml, not at compile time and not at run time.
There you have it, two good reasons to use dynamic when you're interacting with JavaScript. You can get around unknown objects in managed code and you can call operations managed code has no clue of.
Be ready for the next two parts, first on dynamic and Excel and next about ExpandoObjects (this is where the fun begins!).
As mentioned in the previous post, dynamic programming can help you a lot when working with COM objects. I will give an example of this for JavaScript objects in a small Silverlight application. In the next post I will extend this simple example and I will explain interaction with Excel. But first, let’s talk about JavaScript.
Interacting with JavaScript might be something you need in real life. For instance if you have a Silverlight app that is hosted on a page that relies on JQuery a lot. JQuery can provide you with objects your SilverLight application does not know about. How can you interact with these objects if your managed code doesn’t know their type? The answer is to utilize dynamic.
To illustrate this, suppose we have a service running that can give us data about persons. A Person being just a DTO class with a FirstName and LastName property. Plain and simple.
[ServiceContract]
public interface IDataService
{
[OperationContract]
List<Person> GetData();
}
[DataContract]
public class Person
{
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
I also have a HTML page that includes a SuperPerson object. A SuperPerson being the same as a Person, but with one extra property, 'somethingextra'.
function SuperPerson(firstname, lastname, somethingextra) { this.firstname = firstname; this.lastname = lastname; this.somethingextra = somethingextra;
}There is also a JavaScript function that can create one of these SuperPerson objects with the extra data.function GetSuperPerson(firstname, lastname, somethingextra) { var person = new SuperPerson(firstname, lastname, somethingextra); return person;
}To illustrate how to work with such a JavaScript object, I’ve made a small Silverlight application that receives a list of person objects from the WCF service described above. The Silverlight application will display this list of persons in a DataGrid control. public MainPage(){
InitializeComponent();
DataService.DataServiceClient client = new DataService.DataServiceClient();
client.GetDataCompleted += new EventHandler<DataService.GetDataCompletedEventArgs>(client_GetDataCompleted);
client.GetDataAsync();
}
void client_GetDataCompleted(object sender, DataService.GetDataCompletedEventArgs e)
{
dataGrid1.ItemsSource = e.Result;
}
This is the basic set up I will use in this example. The Silverlight application will be hosted on an HTML page that has the above mentioned JavaScript code present. In this example, to keep it simple, I will build a HTML table. It will be the Silverlight code that builds this table, not the JavaScript code. For this, first thing will be to get hold of a specific div tag on the HTML page in which we will build our table. Silverlight lets you interact with the hosting page through the HtmlPage class. This class gives you a Document property that behaves pretty much the same as the document object in JavaScript, which makes it very easy to use.
HtmlElement theDiv = HtmlPage.Document.GetElementById("dynamicDiv");
HtmlElement table = HtmlPage.Document.CreateElement("table");
Next, we will iterate over all Person objects in the DataGrid.foreach (DataService.Person p in dataGrid1.ItemsSource)
{
For each of these Person objects we will execute the GetSuperPerson function, present in the JavaScript of the hosting page. Since the Silverlight application has no knowledge of the SuperPerson type, we will use the capabilities of .NET 4.0. dynamic superperson = HtmlPage.Window.Invoke("GetSuperPerson", p.FirstName, p.LastName, System.DateTime.Now.Millisecond);
With the dynamic keyword in place our compiler does not complain about the SuperPerson type it does not know about. And since we know a SuperPerson has a firstname, lastname and somethingextra, we can interact with it though these operations with no problem. HtmlElement row = HtmlPage.Document.CreateElement("tr");
dynamic td = HtmlPage.Document.CreateElement("td");
td.innerHTML = superperson.firstname;
row.AppendChild(td);
td = HtmlPage.Document.CreateElement("td");
td.innerHTML = superperson.lastname;
row.AppendChild(td);
td = HtmlPage.Document.CreateElement("td");
td.innerHTML = superperson.somethingextra;
row.AppendChild(td);
table.AppendChild(row);
}
theDiv.AppendChild(table);
Two things are notable about the code above. First of all, I use firstname and lastname, not FirstName and LastName (mind the casing). This is because we are interacting with the JavaScript object, not with the original Person object. I purposely used other casing in the JavaScript code to make my point on this clear.A second thing you may have noticed is a second use of the dynamic keyword. When I create a new td element, I do not use the HtmlElement type (which is valid for a td tag), but instead I use the dynamic keyword. I do this because I know for sure it is possible to call the innerHtml operation on a td tag. The HtmlElement, however, does not have this operation present (you can check this in your intellisense). There is also no specific type for a td element that does have this operation present. With dynamic there is no problem at all to call innerHtml, not at compile time and not at run time.
There you have it, two good reasons to use dynamic when you're interacting with JavaScript. You can get around unknown objects in managed code and you can call operations managed code has no clue of.
Be ready for the next two parts, first on dynamic and Excel and next about ExpandoObjects (this is where the fun begins!).
Labels:
.Net,
C#,
dynamic,
JavaScript,
Silverlight
Subscribe to:
Posts (Atom)



