00:01We're going to be talking about MVVM and custom controls.
00:04So I'm going to start by introducing myself. My name is Bernardo Castilho.
00:08I work for ComponentOne. I'm CTO and cofounder. That's my e-mail over there.
00:14Before I actually start, I'd like to get a quick show of hands so I know who you guys are.
00:19Who here is working with Silverlight? Who's developing applications with Silverlight? Great.
00:24So who's using MVVM? Pretty much everybody. Awesome. Okay, great. Thank you.
00:31So I'll give a quick definition what MVVM is.
00:34MVVM is an architectural pattern that created, was introduced by Microsoft when their VPF first came out.
00:41And the reason they created that was, they realized there were two types of developers working on these apps.
00:46There were the designer-type guys using declarative languages like XAML, in this case...
00:51...and the more traditional developer guys using C#, VB, C++, and Java, those types of languages.
00:59These two types of developer use different tools, use either Blend or Visual Studio.
01:04Sometimes it's actually the same person, but they're just wearing different hats and different tools...
01:07...so it's a different type of environment.
01:11So the idea is to split up the application into layers so those things can be tested and developed and maintained independently.
01:19And you got a lot more stability that way.
01:23So the view model part is the middle layer. What it does is...
01:27...it exposes model data so that it can be easily consumed by the views.
01:33So the diagram that you look at is usually something like this.
01:36On one end, you have the model, and that's the code that talks to the database and so on and so forth.
01:41At the other end of the spectrum, you have a view, and that's created using the declarative languages.
01:47And then in the middle you have this, this view model part that acts as a broker between the two.
01:53The name view model, you have to think of it not as something that's partly view and partly model.
01:58The view model is really a model, but it's a model that serves the view. That's what it is.
02:04The demarcation between these layers is subject to discussion, exploration.
02:08If you go to Google and start reading about MVVM, you'll see a lot of arguments...
02:11...discussion going on about what layer should a specific part of the application be assigned to.
02:18We're not too concerned about that here. It's usually fairly easy to find out what should be done.
02:24So we're going to focus more on the practical implementation and then the beginnings, the introduction portion.
02:31There's a couple of links here you may find useful. You're going to get a copy of the slides.
02:35I encourage you to take a look at those links, especially the second one. It's a very nice article by Nequel Katari.
02:42So now let's start dissecting the MVVM model, piece by piece.
02:46We'll start with the model. The model is the part of the application that typically runs on the server.
02:51And it provides a relatively low access, low-level access to the DB and it's mostly autogenerated code.
02:58So if you're using Visual Studio and you add an [unintelligible] .NET data source...
03:03...or you add an OData service, you're going to get a lot of code generated for you automatically.
03:10And those are those partial classes that map into objects in the database.
03:16So you usually don't have to worry too much about that part.
03:20At the other end of the spectrum, you have the view.
03:24And the view's written, it consists mostly or only of XAML, and that's the part done by the designers.
03:30And that's...you have to remember, the view is not written to programming language.
03:36XAML is a declarative language, it's markup, so you have a lot less power than you would with a regular programming language.
03:43So there isn't really a clear pathway between these two. They can't...they don't speak the same language.
03:47The don't communicate, and that's why you need the view model to act as a broker between the two.
03:54So the job of the view model is to expose these model classes to the view so they can be consumed easily by your XAML.
04:03One of the most important things about the MVVM architecture, one of the greatest advantages that you get...
04:09...is that the view model class is testable. It doesn't have any NEUI, so you can use Unitest for everything.
04:15And you can know that your view model is a solid foundation for all your views.
04:19So if you're doing MVVM, you should be taking advantage of that.
04:26So I said that the view model acts as a broker between the model and the view.
04:32Let's see how that communication actually happens.
04:36So the communication between the model and the view model normally consists of cost web services, right?
04:42So the model exposes services, the view model instantiates the service client, makes a call to get the data...
04:49...and all these calls are asynchronous, so they don't return immediately.
04:54The server...the application goes out to the web to get the data.
04:57When the data comes back, an event is raised...
05:00...and then your view model can add that data to the collections and expose it to the view.
05:04But it happens asynchronously. So, this is not really an MVVM-specific type of pattern.
05:10You've all used it. I'm sure you're familiar with it.
05:13The more interesting thing happens over here, in the communication between the view and the view model.
05:19And that's done through bindings, and those are also familiar to anybody who has used XAML before.
05:25The binding allows you to connect a property. In the view model, the properties and those objects that are on your view.
05:34So the simplest type of bindings is just scale of properties.
05:37I want to bind a text block...the text property in the text block object through the name property of my customer, right?
05:43So when the customer...currently selected customer changes, that text block gets updated automatically.
05:51In addition to this simple type of binding, there's two special types.
05:56One is things that are bound to collections. So you typically bind to ICollectionView objects.
06:02And what happens then is the ICollectionView's responsible for issuing notifications...
06:07...whenever items are added or removed from that collection...
06:10...when the collection is filtered or when the current item changes.
06:14That's an important thing about ICollectionView, is it has the notion of the current item; you have currency.
06:21The other special kind of binding that some of you might not be familiar with...
06:25...because it's relatively new compared to the others, is the ICommand.
06:30The ICommand interface is an object that you bind to the command property in elements like buttons and menu items...
06:38...anything that triggers an action.
06:40And the ICommand provides the way to make that action happen, to invoke that action.
06:46But in addition to that, it also provides a way for the button or menu item to know...
06:51...whether that action is currently allowed for the current state of the object, of the view model.
06:58So what happens is, and you're going to see that in our sample in a few minutes...
07:02...if you're currently looking at the first item in a collection, for example...
07:05...and you have a button that allows you to go back, that button will be disabled automatically...
07:10...because the command knows that that's not a valid action for the current state of the view model.
07:18Finally, since this is MVVM and custom controls, I added a block to talk about controls very briefly.
07:24And controls are sometimes taken for granted because they come with Visual Studio.
07:27You just use them without thinking about them; you use the text boxes, the buttons, the list boxes.
07:32But you have to remember, those are just regular classes.
07:34You can create your own, you can buy controls from commercial vendors, you can download them from the web.
07:41There's a super rich ecosystem and these controls can really save you a lot of time and simplify your apps.
07:47So you kind of owe it to yourself to do a little research and think about if they can help implement your application.
07:57In the sample app that I'm about to show you, we're going to use four custom controls for different reasons.
08:03We're going to use a gauge that has like a needle effect that sort of bounces around...
08:08...and we do that just for instant gratification, just to make it look prettier.
08:11That's one reason for custom controls.
08:14We're going to us a map navigation control that we use just to eliminate a dependency on the Esri toolkit assembly.
08:23So instead of taking dependency on that assembly, which is pretty large, we just implemented our own.
08:29And you're going to get the source code to all this in case you want to use it.
08:33Another reason is you're going to [unintelligible] a flip panel, transition panel control...
08:40...that I'm going to show you as well, and that's...that was used here to better support MVVM...
08:44...'cause I didn't want to add the job of keeping track of the current view to my view model...
08:49...so I delegated that to my view in the form of a control.
08:53And finally, if you write your own custom controls and they're generic...
08:56...they don't depend on your specific view model, then you can reuse them.
09:00They become part of your toolbox. And we're going to see one of those too.
09:05So the sample application. Here's the sketch of the view that I had in mind.
09:10I wanted to create a dashboard application, and this is not a typical mapcentric application.
09:15See, typically in the Esri world, it's more a business application.
09:19I want to show sales data for Northwind. My dashboard is going to show the current quarter that I'm looking at.
09:25I'm going to add some navigation buttons so I can go to previous or next quarters.
09:30Below that, I want to show a gauge showing the sales for this quarter and my sales goals.
09:37Whenever I select a different quarter, the gauge is going to be updated automatically.
09:41Then on the other side of the app, I want to show three controls.
09:44I want to show a map and I want to show the sales by customer at their locations.
09:48And the idea here is, as I navigate through the quarters, I can see, maybe, sales patterns emerging geographically.
09:56See what's happening, the sales in Europe are going up, South America going down, patterns like those.
10:02I also want to show a chart, a traditional chart, that will show sales by category, how they vary across the quarters.
10:10And finally, I want to show a grid. And the main reason for the grid...
10:13...is just to allow people to copy that information and paste it into Excel and do further analysis...
10:18...because Excel's such a great tool. If we can provide a bridge to that tool, why not do it, right?
10:24So, let me show you the app, if I can figure out the keys on the Mac. Here.
10:32So this is what the app looks like. This is the final result, and then we're going to go through the implementation a little bit.
10:38So this is the fourth quarter 2009; here's the navigation buttons that I told you about.
10:43I can click here. I can see, the needle on the gauge moves to reflect the current sales...
10:48...and I can see the patterns, the sales on a map changing.
10:57If I want to look at sales by customer, that's how it's done.
11:01I can flip that panel here and show sales by product category, and the map's gone and I've got this chart.
11:07And if I want to see a grid, I do it once again, and I got my grid and I can select that information, copy it in Excel.
11:16So let's go back to the presentation and dissect that.
11:21So, the first thing that I got when I drew that diagram was, I knew what elements I needed to feed that view, right?
11:28So those are the view model requirements. I knew that my view model had to give me three collections.
11:35Collection of quarters, so the user can see what quarter's currently selected.
11:38I can filter by quarter and select different ones, navigate through them.
11:42So that's ICollectionView, of course.
11:45I needed a sales by customer and sales by category collections to feed my map and my chart, right?
11:51And those are just regular collection views, this time filtered by quarters.
11:55So when the current quarter changes, those two collections are filtered and the view automatically updates itself.
12:03In addition to those three collections, I need three properties.
12:06The current sales, the goals, gold and platinum, and those are the ones that are going to drive my gauge.
12:13And a few commands to drive those VCR buttons.
12:16I could have used like a scroll bar as well or a slider or something, but in this case I chose to use VCR buttons.
12:22So I have select first, previous, next, then last quarter.
12:27Finally, I thought I'd mention data extensions.
12:30The data that came from my model doesn't have a quarter property, for example. I have sales or to date.
12:37I'm going to group by quarter. But because those classes were generated automatically...
12:41...and they're partial classes, I can add properties to them.
12:45So this is what I did in this case. And you can take a look at the source code later; you'll see that it's very simple.
12:51This is just a calculated property. You grab the date, convert it into a string that represents the quarter...
12:57...and that becomes part of my data model, even though it's not in the raw data object.
13:02I did the same thing to get the amount and to get, most importantly...
13:05...latitude and longitude properties, which are attached to the customer.
13:09'Cause the customer class in Northwind has an address, but they don't have latitude/longitude.
13:14So I ran a geocoding process in parallel, outside of the app, added that information to my application.
13:22And that's the view model.
13:25So now let's take a look at how the view is implemented.
13:31Sorry, let's look at how the view model is implemented.
13:32This is the constructor for my view model class. It's kind of...I shouldn't have called it "View Model"...
13:39...because it might be confusing, but this is the view model and it's called View Model.
13:43The first thing that I do is load raw data. This is the part that grabs the data from the model part.
13:49In this case, I didn't bother to do it asynchronously because I wanted the sample to be very simple and easy to understand.
13:55So it grabs it synchronously. I just load everything--customer, sales, all the Northwind data that I want.
14:02Once I have that data, I create a list of distinct quarters, and I do that using a link statement.
14:08And I feed that to an ObservableCollection. And it's important to use ObservableCollection...
14:13...especially in asynch scenarios, which this one isn't, but in real life it, will be...
14:18...because then whenever I update that ObservableCollection, the collection view that's bound to that...
14:23...is going to issue the, broadcast the events and everything's going to be updated properly the way it should.
14:30So once I have my ObservableCollection full, this is where I create the collection view.
14:34This is the binding guy, the real property.
14:38And the way you do that is, use a CollectionViewSource class, which is part of the framework.
14:42You tell it what the source collection is.
14:44It's an ObservableCollection which I created here, and that becomes my property that my view model exposes.
14:52Right here, I bind an event handler to the current changed, so that when the user selects a different quarter...
14:58...that event fires and then I can update the filters for the other collections.
15:03The slide's not here. It says By Customer and By Category.
15:07And I can also update the sales for this quarter and the goals.
15:15Here's the implementation of the commands.
15:19The ICommand interface has two methods. One is skin execute, and this is the one that's used to enable and disable the buttons.
15:27And in this case, my select quarter command has an offset, which is the number of quarters I want to move back or forth.
15:35If the offset is negative, this guy's going to...can execute only from...at a position greater than zero...
15:41...'cause you can't move backwards from zero.
15:43And the same thing, if the offset is positive, you can only go forward if you're not at the last item.
15:48So just that single statement there, that little bit of code...
15:52...is enough to enable and disable all these buttons, all of this view and other views. I had other views.
15:59Then the execute command is pretty easy to implement too...
16:02...because we leverage the CollectionView that we already have, we grab the quarters...
16:07...offset is -1. I move to previous, offset is +1; I move to next.
16:11I can move to first or to last. So that's the implementation of the command. So that's pretty easy to do.
16:19Now let's look at the implementation for the view.
16:22So this is the XAML code. The first thing that I'm doing is I'm instantiating a view model up there, right?
16:30That's the resources for this page.
16:39There's nothing special about view model. It's not a property or anything. That's just the class.
16:43So what that statement does is, it creates an instance of the class view model, and that's just the class name.
16:48...I'm saying, okay, the data context for this grid element...
16:51...and everything in it is that view model that I instantiated in the line above.
16:58So that first...this is what allows me to bind things to the properties in that view model.
17:05So all I have to do is specify the name of the property I want to bind to and I'm done.
17:10So let's look at, for example, that text block up there that shows the current quarter, it's a text block.
17:16The text property on that text block object is set to quarters.currentitem.
17:22The quarters is a property of my view model, which is the data context.
17:26So this is all that I need to do.
17:28To navigate the quarters, I use four hyperlink buttons, those VCR guys there.
17:35And what I do is, I bind the command property on those buttons to the previous quarter, first, last, next.
17:41That's all that I have to do in my view.
17:45Finally, this gauge. This is the first custom control [unintelligible].
17:50So this one's the animated gauge. It inherits from the regular gauge...
17:53...and the only thing that it does is add a little bouncing effect to the needle when the value changes.
18:00So I bind the value on that gauge to the quarter sales...
18:04...and then I use bindings to create these ranges here to the ranges that show the gold and platinum goals.
18:11So the gold range goes from gold to platinum.
18:15The platinum range goes from platinum to the maximum value, which is half a million.
18:25Then we come to the interesting part, the map.
18:28The map is an Esri map control and it takes advantage of this point data source class.
18:34This was added, I believe, in version 2.3 of the map...
18:37...and it makes MVVM programming very easy with the Esri map.
18:42All you have to do is tell this class here what the item source is, and in our case, it's sales by customer.
18:49And then the items on that map, the x coordinate is going to be bound to the longitude...
18:53...the y to the latitude, and that's all it takes.
18:58I also have to define the symbol that's going to be, the marker that's going to be used.
19:02And in this case, I...the symbol's just an ellipse, and it's bound to the scale property...
19:09...so that places with more sales show a bigger ellipsis. Yeah?
19:13[Inaudible audience comment]
19:21Right. So I can...I can show you that at the end, but it's a separate element in the renderer.
19:28There's a marker template, and that's just another XAML element. It could be anything.
19:33In this case, it's just an elipse, and the size is done by doing a scale transform.
19:40And the scale transform is also bound to a property of that point, right?
19:44I'll be happy to show you the source code later. I don't have Visual Studio here.
19:48But I'll show that later. And this is our map navigator control, which is our second or third custom control.
19:57It's the one I told you about. I didn't want to take that dependency...
19:59...so I just wrote one with a couple of buttons, and it's very easy to do.
20:07And then up there on the top right, you've got that button that switches the panels...
20:14...flips between the map and the chart and the grid.
20:18And that's also been with the custom control.
20:20And that custom control has one command and the command is called Switch Panel.
20:25So what I do is, I bind that hyperlink button to the Switch Panel command.
20:30And here's an interesting thing. In this case, I'm not binding my view to my view model.
20:35I'm binding within the view itself.
20:38So I'm applying this command to the Switch Panel command all of the elements transition panel...
20:45...which is something...the panel that holds all these things together.
20:48So the view model's not even aware of this. It's totally within the view.
20:58And this is all the C# code behind this page.
21:01It's just initialized component, which is automatic, so there's no code at all.
21:09Let me just go back to the app a little bit, just once again to show you a few more features.
21:15So like I already showed that when you change the current quarter, the gauge updates automatically.
21:22You saw, oops, you saw that the map updates automatically as well.
21:28And maybe my strategy team in my sales department can see interesting patterns that are useful to them here.
21:36So it's nice to look at data instead of looking at charts all the time.
21:39Sometimes it's...I don't have to tell you about this, to see the spatial patterns on a map.
21:45But the same thing happens on a chart.
21:46So it's the same thing except the chart doesn't have a geographic scale to it, dimension.
21:54And finally, the grid. The grid is another custom control.
21:57We're extending a standard grid here, but we added an extra capability...
22:02...which is if I double-click on any numeric column, that column automatically turns into a chart.
22:08And this is something that was not done specifically for this app...
22:11...but it's an example of those things that you add, and it's generic, and I just put in my toolbox.
22:15So whenever I have to reuse that, I can just grab it and plop it in; it just works.
22:20So it's a nice type of technique to have. Show you one final thing here.
22:29I selected Ctrl A to select everything and it's Ctrl C to copy.
22:34Now I can go to Excel, whoops, and go Ctrl V to paste, and I got all my data here...
22:45...and I can now insert a pivot table if I want, and show my sales by customer, by mount in a nice pivot table...
22:57...and do all the analysis that I want using Excel.
23:06I'm going back to the app, to the presentation.
23:09So I'm going to finish with my personal MVVM tips.
23:12I'm not an MVVM guru, but I've been doing this for a little while...
23:15...and I think some of these might be useful to you.
23:18The first one's probably the most important, is if you're going to use MVVM...
23:22...then you have to take advantage of MVVM.
23:25Like, spend time designing and testing your view model.
23:30Number two is, leverage the platform. Use CollectionViewSource. Use ObservableCollection. Use ICommand.
23:38Remember to...that your view model should implement INotifyPropertyChanged...
23:42...and remember to raise those events when the properties change...
23:44...otherwise your view's going to be dead and you're not going to know why.
23:48In other words, leverage the platform.
23:49Don't...try not to reinvent the wheel, 'cause you could save yourself a lot of time by doing that.
23:55Number three, use binding converters only when necessary. This is one of my favorite ones.
24:00A binding converter is necessary when you want to bind, like, a property that's a numeric value to a color...
24:06...or to a Boolean to a visability or things that have incompatible types.
24:10That's why you should use converters. And only for that.
24:13You know, I've seen people use converters to format numeric values into strings.
24:18There's...binding that string format property for that. That's what you should use in those cases.
24:25The converters can take a parameter. I've seen people pass the view model as a parameter to the converter.
24:32That makes no sense. You should...if you're doing that...
24:34...then consider adding a new property to the view model and binding to that instead...
24:38...because what you're doing is, you're spreading out your logic and making things more complicated.
24:43So, in short, use converters only when the types are incompatible and you need to make them compatible.
24:50That's what they're for.
24:52Number four, use custom controls in frameworks. They're out there to help you.
24:55They're available. I didn't talk about frameworks [unintelligible] frameworks.
24:59There's quite a few available, and they can really help.
25:04And finally, number five, if you have to use some code behind, don't be too crazy.
25:08You know, don't be too paranoid, don't be shy. Just go ahead and do it.
25:11A little bit of code behind is better than compromising your design and finding all these hacks just to avoid that.
25:17And that's the end of presentation. I have a few resources here.
25:22The first link is the sample that I was showing you before.
25:26The second one is the source code. You can go there, you can download it, or you can browse it online.
25:31If you want to download it and build it yourself, then there's a couple of requirements.
25:35You need the Esri Silverlight SDK, version 2.3 or later.
25:40And the component [unintelligible] for Silverlight, which contains the chart and the grid and the gauge controls that you saw.
25:46And that's the end of it. That's my e-mail in case you have feedback, if you want to discuss any of this further.
Introduction to MVVM and Custom Controls
Bernardo Castilho of ComponentOne discusses the role custom controls play in MVVM applications.
- Recorded: Mar 28th, 2012
- Runtime: 26:00
- Views: 859
- Published: Apr 30th, 2012
- Night Mode (Off)Automatically dim the web site while the video is playing. A few seconds after you start watching the video and stop moving your mouse, your screen will dim. You can auto save this option if you login.
- HTML5 Video (Off) Play videos using HTML5 Video instead of flash. A modern web browser is required to view videos using HTML5.