>> Sam Landstrom: All right. So I created... Microsoft, and I did this is as a moonlighting project...

advertisement
>> Sam Landstrom: All right. So I created Wizard's Choice. I'm a -- I work for
Microsoft, and I did this is as a moonlighting project on the side. It was originally
Windows phone app, and I ported it over to Windows Store.
And anyway, the -- all right. So basically what's interesting about Wizard's Choice is
what it isn't, which is to say it's not a very sophisticated app. This is a sub '80s level text
adventure. We're talking not even Zork level, where you type in commands like open
door or something. This is just literally making choices, choose your own adventure on
steroids, perhaps.
But I've gotten quite a few downloads. And so what I thought might be interesting to talk
about is kind of what I thought went into to getting these downloads. Over close to a
million now. And it's getting great ratings.
So I don't think it's so much a matter of having an app that's really flashy, but just one
that's very easy to use and is fun to play. Well, in this case it's a game, so play.
So, yeah, power of free. I give it away mostly and make money off of ads. Kept it
simple. The great store art and icons, invested a lot into art, what little art I have. And I
encouraged my users to help me to spread the word.
So I'll go on to some of that. Yes. So used monetization schemes that allowed me to
give it away for free. As I mentioned you've got to do it free. I mean, if you -- at least if
you want to get a lot of distribution. I have tried doing lost leader log, where I'll give
away the first game and then have the SQLs charge for those. It actually works pretty
well on some platforms, but for this I find it much more rewarding just to give away the
whole thing and just make some money off of apps.
So and actually I have a blog post about making money, if you want to read that. Yes,
kept it simple. So here's the level of -- this is the height of complexity of this game. So
literally you just making choices. You just read, make choices, read make choice. You
might see some notifications based on, you know, whether or not your choice was
advantageous or not. But, yeah, there's not much to -- not value a feed of engineering
by any means.
I did invest some money into hiring some artists to give me some decent logos. So as
you can see up there, you can probably pick my stuff out a little bit. And that really
helped me I think to attract eyeballs. And it's remained in the top 100 for free games,
both on store and on phone for months. And I think a lot of it has to do with art. And so
not just the -- that little 50 by 50 pixel square logo, which I think is crucial, but also your
logo once you're on the store or once you're on the start menu so people can pick you
out.
The woman with the dagger there, I -- personally, I would click on that. But, anyway.
So how I did that is I hired my artists through elance and guru.com. It costs you a
couple hundred bucks. But let's face it. I don't think most of you are necessarily artists.
Or if you think you're an artist, you're probably not really an artist. And so I know I'm not
an artist at all. So I really am glad I went through this route, so -- not only for that, but
for editing. And of course you can also hire them for coding if you want, but maybe if
you want a widget or something. I've heard that that's actually usually what people use
those websites for.
All right. So I had asked for help from my users shamelessly. Of please rate the app,
preferably a good one, which I guess is what I'm doing now. I didn't all know that you
were going to rate it five but I guess now that you are that's good to know. And I also
would point them to my Facebook page, which came in really -- became really important
later strategically.
As you can see on Facebook, you start getting a whole -- of course, it doesn't matter
what outlet you have, but you have to have a outlet through your customers to give you
feedback because I found a lot of bugs this way. And I also get a lot of five star ratings
to begin with, because I have fans that are following me. And I'm close to a thousand
now on here. And when you just distribute and say I've got a new app out, a bunch of
people have downloaded initially, pump up your ratings really quick and then also give
you quick feedback, mainly just because my testing is -- I try to test it.
But in the end, I test it in production. So, anyway. You're raising your hand?
>>: Yes. Is your Facebook page your personal Facebook page or one you developed
for Wizard's Choice?
>> Sam Landstrom: I have both. And at first people were friending me on Facebook
and that wasn't working very well, that didn't scale. So, yeah, I created one for -- it says
Sam Landstrom and that has to do with my authoring because I like to write. I have a
novel too. But anyway, what I normally would do is I would have changed that to do you
like games. And that's what I'll probably do later as I spit out more games.
>>: Got it. Cool.
>> Sam Landstrom: Yeah. Normally you wouldn't probably put your name on there as
your Facebook page or whatever website you're using.
And that's the main step. It's like basically keep it dead simple so I don't have many
bugs. I have the advantage of the fact that my content was kind of what drove value to
it while the shell itself was very simple. And so what it did, it did really well. Again, I got
people to try to help me by being shameless about my plugs in there. Great art. And
then just having a good feedback loop with my customers. That's basically it, I think.
So questions?
>>: [inaudible] from the phone to Windows? You have [inaudible].
>> Sam Landstrom: It -- because it was such a dead simple framework, so I had a
simple framework around it, and then I just swap XML files. So in XML file I'll use to
define the game. So basically how the store goes, what decisions you can make, what
are the consequences, all that I determine in an XML file. But it dead simple framework
around it.
And, yeah, I just -- I ported it over in probably about a day. The hardest thing was
adding a few new features for Windows 8 like an app purchase. But otherwise it was a
pretty quick and easy port because of how simple it was to begin with. Your results may
vary. Yes?
>>: How many downloads have you had for your upgrade scenarios on top of the ones
that you've had for the -- your free case?
>> Sam Landstrom: Oh, right, so for the InApp purchase? That, not as many as I had
hoped. About -- let's see. I made about 650 bucks off of the Windows store version.
So that's like maybe 320 -- it's like 2 bucks a pop. So, yeah. I give the first three
chapters away for free and then they get hit with the InApp purchase. And honestly, I
thing a loss leader model is probably better, where you give away the first chapter and
then you charge for each one after.
I'm trying to work out why that is, but I've seen it on other platforms and it's more
effective, strangely, in some cases. I think it's because you trust the app more going up
on the store and seeing it and seeing its ratings versus having this chrome that shows
up where it's asking for your credit card right in the app.
Especially with an app that looks as crude as mine. You're like is this guy phishing me?
What's going on? And so I haven't seen as many InApp purchases as I'd like to see.
And I'm thinking of rereleasing it as free and just have ads for it.
>>: If you don't mind asking me, how much are you getting from the ads revenue?
>> Sam Landstrom: Recently like maybe 30 bucks a day. And ->>: That's great.
>> Sam Landstrom: Yeah. That's mostly off phone though. Well, actually I don't have
ads on the Windows Store version. But off of phone, yeah, but that's just because I did
a new release. It's usually more like 15, $20 a day.
But, yeah, my ECPMs are not very high. I wish my app was more sticky so people were
-- the problem with the text adventure is once they burn through it, they're done. Unlike
a card game, for instance, where you can make a lot of money.
>>: [inaudible].
>> Sam Landstrom: Yeah. And I'm hiring writers again through that websites because
writers are cheap. So, anyway.
>>: By the way, do you keep statistics about what choices the readers did?
>> Sam Landstrom: I'd like to do that. I was thinking of hooking this up to the cloud and
just having a few things like, okay, I have stats at the end like where you rank and then
it gives you a title like you're anything from like wetter of the trousers all the way to
grand champion of whatever.
And what I like to do is hook that up to the cloud so I can start seeing how people are
scoring and see where the bell curve is, and then see how you compare to others more
directly, versus kind of my evaluation of how you did.
And also, yes, it would be cool after each choice to see stats, see what everybody else
was doing. So those are kind of features I've been thinking of adding.
>> Francis Cheung: Well, all right. How is everyone doing today? Okay. My name is
Francis Cheung. I work for Patterns and Practices. Anybody heard of Patterns and
Practices before? Four, five. Okay. So what we do is we provide guidance. Guidance
is oftentimes terms in the form of books. We also write a lot of code.
Anybody use Unity, Enterprise Library? Okay. So ->>: [inaudible].
>> Francis Cheung: It says yes. Hello. Can you not hear me?
>>: [inaudible].
>> Francis Cheung: Oh, there we go.
>>: Perfect.
>> Francis Cheung: We're green. We're very green now.
All right. So Patterns and Practices we produce books, we produce reusable libraries
like Enterprise Library, Unity, and Prism. So let me give you a little bit of background
about what we're going to be talking about today. I'll be giving you some tips and tricks
on Windows 8 development but mainly concentrated on building business style apps,
line of business style apps. That's what we really are focusing on. That's generally our
customers, the enterprise customers. So that's really what -- where we focus our tips
and tricks.
So to give you some background, Kona really started because of Prism. Prism was the
framework that we came out with that was really to help business customers, enterprise
customers build line of business style composable applications on WPF. Okay.
Anybody heard of CAB, composite application for app block? Okay. You go way back.
You get a reward for CAB. Now, we created CAB for Windows forums. And initially we
said some -- a lot of customers said hey, let's go ahead and port CAB to WPF. Well,
luckily we didn't listen to them.
We thought, well, what do people really want to do in WPF that they need help with?
What are the problems, what are the pain points in WPF? So we rethought what they
wanted. Said, well, what do you want? Do you want composability, do you want
modularity? What do these things look like in this new platform? And we readdressed
those scenarios.
Fast forward five years those same customers are asking us now, hey, can you please
port Prism to Windows Store? And we said absolutely not. We rethought these
scenarios and said, hey, what do people need help with in Windows Store? We don't
know. So we set out to build an application to find out.
So let's take a look at this application here. It's a web based application, I know. But
imagine it's, let's say, a desktop or WPF application. See if you can spot any
differences or similarities between it and the Windows Store version. Let's see.
Again, web, Windows Store. Any similarities? I'll do it again really slow. Web,
Windows Store. Anyway, the point is that there's such a big difference in platform, in
functionality, in user experience that in a lot of the same challenges you had in WPF
don't apply. For example, one thing that we spent a lot of time with in Prism was
composability, right? You had code coming from different modules, from different
teams. You need to assemble a user interface with all the -- these different
components.
How does that work in Windows Store? Well, Windows Store apps aren't like that,
right? They're typically really simple screens. You want to do a simple task on that
screen. You don't have 10 little subwindows on this screen. They're all inner working.
You don't really have that.
So we don't have the same composability challenges or needs on this platform.
So what we decided to do is build a shopping cart style app in Windows 8 using C# and
XAML because that's what most of our enterprise developers were using. That was the
tool set they were using. And so we wanted to make sure it was bulletproof, it was
world ready, it was built on the technologies that we wanted to really showcase.
So we built out this app, and as typical for Patterns and Practices we like to build the
app first and then see what kind of things were really reusable, and we pulled them out.
And so that's what we did. So we'll be shipping the app here, which is the
AdventureWorks shopper, based on the adventure works database and SQL server, as
well as some reusable libraries. And we'll be shipping in May 2013.
So let me give you a quick demo of the AdventureWorks Shopper.
>>: [inaudible].
>> Francis Cheung: Sorry. 2013.
>>: Okay. There you go. Okay. So here's our app. We went ahead and shot some
nice images as opposed to the images that were in the AdventureWorks database. So
you can see here you can dive into different categories. This is the hub page and so
you can see us scrolling here. And you get some semantic zoom here. And go to a
certain scroll -- scroll to the right you can zoom into this category. You can go to the
product details, add to the shopping cart. You know, pretty typical shopping cart type
app, right?
And we showcased a lot of different things here. For example, here's an example of
composition. So what you have here is a page with three constituent parts. Here
you've got address, billing and payment. These three different forms are used in the
other parts -- parts of the application where you want to, let's say, add a specific
shipping address, or you want to edit a payment method and so forth.
So we have some composition here, and we also have to deal with situations like for
example here. If you hit submit without anything in the form, you get a whole bunch of
validation problems, right? And, sure enough, let's say if we were to put some data in
here, go back up to the Visual Studio, suspend your application, launch it. What do you
expect to happen? What do you expect to see? You expect to see exactly what we left
from, right? That, itself, is pretty hard to do. The validation's hard to do. Keeping the
stored state is hard to do. A lot of it's pretty hard to do.
In addition, this is actually not at the page level. These are user controls within the
page. So he has that level of composability that is also kind of hard to do. So after we
built the app, just let me go back to the Power Point here again, we look at what is so
commonly used in the app and figured is this useful enough to ship as a reusable
library? And we found a number of components that were.
And so we'd like to introduce Prism for Windows Runtime. If you use Prism before,
we've released Prism 4.1 for WPF and Windows Phone and Silverlight. This is a
completely new thing. It's Prism for Windows Runtime.
It provides MVVM support, navigation, decoupled communication. Anybody use event
aggregator? Nobody? Boy. Tough crowd. Decoupled communication is all about the
event aggregator. We decided to actually pull it out of Prism and put it in a portable
cuffs library so you could even use it in Xbox if you wanted to.
Commands, support, validation support as well as flyout support. Anybody create
flyouts in Windows? Windows 8? It's pretty fun, isn't it? It's -- is it a lot of work?
>>: Yeah.
>> Francis Cheung: To create a flyout? Yeah. I'll show you it will be like three lines of
code for us. It will be super easy. So flyout support is something that I think is going to
be a big win for you guys.
So let's move on to tips and lessons learned. Again, what we do is we provide guidance
by really experiencing it and having a test team hammer on our code. They look at
every line of code. So this is where we provide value. Most of our corporate customers
don't have the time to experiment with five different ways of doing every little thing and
seeing which way is the best. That's what we do. We look at every option, or at least
most of the options that is we like to entertain, and we have our test team -- we build it
out. If we don't like it, we build it again. If our test team doesn't like it, we build it again,
so forth, so on. Right.
Let's start with the first tip. These tips are pretty general. First tip is that, hey, you know
what, if you're a Windows 8 -- sorry, Windows Phone developer, Windows Phone,
Mango or even Pre-Mango, Windows Phone 7 developer, the transition to Windows
Store apps is going to be pretty straightforward. There's just a few things different.
For example, suspend, terminate, resume experience is very similar to deactivate,
tombstone and reactivate. So if you had to worry about that before, this is going to be
pretty similar.
The push notification service is very similar to the new WNS. Pretty similar. A little bit
different, but pretty similar.
Also, you've got to go through the same or similar certification process with Windows
Phone you have a certification, with Windows Store apps you have a slightly different
certification process. They're going to look for different things, but you also have that
layer before you get your app submitted.
By the way, if you have any questions about anything I say up here, or if you have a
comment, please let me know. All right?
Tip number two -- again, these are pretty general. If you haven't done any Windows
Store app development, this might be useful to you. My point here is that you don't
have a lot of the things that you'd expect if you're doing, for example, WPF or Silverlight
development. For example, blend behaviors. Behavior of T. People build a lot of code
around that. That's not available here.
Binding expressions. You can build a binding expression but you can't get access to it
programatically. So there's a lot of things that you can't do. So if you've been doing
development in Silverlight back -- way back like in Silverlight version 3, your skills are
going to be really needed. So attached behaviors, you're going to be doing a lot of
those. All right.
All right. Next one, push notification. In Windows Store apps, push notification requires
you to register your app with the store because the Windows Store is actually where it's
going to be -- at least it's -- every message is authenticated through the store.
So what happens if you had a sideloaded app? Sideloaded app's probably not going to
be registered with the store. Your enterprises are going to build up these apps,
expecting them to be deployed to your -- your employees or certain customers or so.
They're not going to -- those apps are never going to see the light of the Windows Store
day. Right?
So how do you deal with that? Well, unfortunately right now there is no third party push
notification service. There's only one. So you have to go through the store. So the only
option that we found is to use a periodic notifications. So no push, but you can do a
pull. Right?
Async and await. Now, with the new platform it's really important not to lock the user
interface. Not to lock that UI thread. So typically anything that takes any amount of
time, file, IO, talking to services, that's all going to be async. You know, typically the
APIs that are provided to you are async and so forth. You know, your chain of calls all
the way up are probably going to be async too. As well as any APIs that you write. If
they take any amount of time, they need to be async. Okay?
So for example, anybody done async and await stuff? Half the crowd. Okay. You guys
are probably experts at this already. So you can see here that you got an HTTP client.
The next line creates a task or returns a task, actually uses that client to go hit a URL
and return a task of string. And then we do some work here on line five.
And you can see here, this is all synchronous, right? This goes boom, boom, boom,
boom, boom. Just goes against this until line 7. On line 7, it -- we've got the get string
tasks that we created up here. And we're awaiting it. So now we're going to allow it to
finish and then the UI is now responsive again. You can do other things. And once
that's done, do we do the rest of this method?
So the line 8 is not executed until line 7 finishes. So how does that happen? It looks
like, you know, that would be some sort of callback. Well, all of that's taken care of for
you by the compiler. So all you have to do is put a weight there and the rest of the
method will not get executed until that await finishes.
So really, really useful. We had several different projects use -- well, we had the Halo
projects written in C++ as well as a Win JS. And they're code for asynchronous
programming was much more difficult to write. If you're doing C# development, async
and await are your friends. They're very, very useful. Okay?
Let's talk about navigation. Page-to-page type navigation. What can we do to help with
that experience? You think, well, it's not a big deal to do that kind of stuff? Just let me
make sure I'm on the same page. Okay.
So how do we help with navigation? Number one is to use the visual state aware page.
Now, this is actually something we provide in our framework so I should preface that
with the Prism visual state aware page. This is very, very similar to the layout aware
page. If you've created a new project and use anything other than I think the blank
template you get the layout aware page, right?
So we basically use the layout aware page but ripped out some things that we didn't
really like. Like we have this concept of a view model in the later page that didn't really
match what we thought was view model, so we went ahead and removed that. And we
renamed it something that was more specific to what it does. It really just helps you
with your visual states. Okay?
So your visual state aware page, also it helps with some navigation support. So you've
got some three methods here, go home, go back, and go forward as well as several of
the methods here for a lifetime management.
You'll notice the method signatures. What do those look like? Those are event
handlers, right? So that's kind of funny. How would they provide all these methods
here as event handlers? Do I call it? If I call it what do I provide it? It's kind of funny. I
wondered that the first time I looked at these overloads, these virtual methods.
So here's how you're supposed to use it. Imagine you got a button and you want to go
back when I hit the button. You basically point it to the go-back method, which is
basically just event handler. So you're saying, hey, use the a code in the goback
handler when I hit this button. So that's how you're supposed to use that.
As well as here you can see the loaded event of the user control and the unloaded
event are tied to the start layout updates and stop layout updates. So this is really
important if you -- well all of your apps are going to be able to need to handle all the
various visual states, right? So your apps aren't always just going to be viewed in
landscape, they're going to be viewed in portrait. They'll be viewed in snap. They're
going to be viewed in many different ways. Come Blue there will be even more. So
you're going to need to deal with these.
So in your page, that's one thing. But in your user controls you need to pass this
information down too. So that's how you -- that's how you do that. That's why they look
the way they do. They're actually event handlers. So that's how you're supposed to
wire them up. Okay?
So this is pretty general stuff. If you've been using layout aware page, you've probably
been doing this already. Okay? And here's how you save and load your state. Again,
this is at the page level. This is page state. So what would -- what kind of data would
you want to load and save in your page state? Well, scroll position, number one.
I'll be talking a lot more about view models and the MVVM pattern. But what kind of
stuff would you typically want to save in your page, your scroll position?
So in this case, you can see my horizontal offset is being saved. So I'm pulling it out of
my visualized stock pile and putting it in my page state. Here I'm loading it. Okay?
Pretty typical usage of those two methods.
And next tip is definitely support your visual states. If you're anything like me, you'll be
spending a lot of time here. If you want your apps to look correct in all your various
page states, which you -- which you really need to do. I'm not sure if the review process
is really going to hammer you on this, but you know what, if the user -- if your users just
tilt your app or snap it and you give them nothing, then they're not going to be that
happy, you know.
If you look at the first party apps, I think more and more of them are going to be
supporting this. And it's just a better user experience. If you have data -- if you have
functionality in the full page, you want to have that functionality or have a good reason
for not having that functionality in snap view. Or portrait and so forth. So you'll be
spending a lot of time here.
In this case, blend is your friend. Blend can provide you a lot of this data. In blend you
can change to your different states and then see how it looks. So definitely use blend
for that, okay?
World readiness. Well I'll just scratch the surface here in terms of world readiness and
talk about translations or getting data out of resources. So, for example, let's say you
got a tool tip. And you got some content in your tool tip, so that's what it shows up in,
let's say, in your designer.
But how do you get it in runtime to show the translated data? Well, you provide a UID
here. And then in your source file, you point to -- you basically tell it what you want to
translate. So for example you can see preview cartoonized app R, but in tool tip you
can see the very top it references that dot content. And there's the content. In this
language.
So you create your various resource files in your various locales and you provide that
same -- same keys over here. And the -- at runtime that content up here will get put into
the content of your control. Pretty straightforward? Does anybody use this already?
Okay. A couple of people. It's really useful. Yeah. It's out of the box. But it's really
useful.
All right. The rest of this talk will be on the MVVM pattern. Anybody use MVVM? A
couple people. All right. All right. So I'm not going to sell you on MVVM here. MVVM
I'll just give you 10 seconds on it. If you're interested in testability, maintainability you
want to look at this pattern. This is the -- by far the dominant separator presentation
pattern in XAML stacks, Windows Phone, WPF. I think it -- John Gossman originally
created this pattern on WPF. And it's a really useful pattern through all the XAML
stacks.
So take a look at it if testability, maintainability are important to you. And they should
be. Okay.
So that's enough about MVVM. So given that you want to know about MVVM, the rest
of the talk is important to you.
So navigation. Imagine that you're in a view model, okay, a view model being the place
where you're going to put your business logic that your view cares about, right?
Typically the place where it calls the databases or calls various services, aggregates a
whole bunch of information in order to paint your screen. That's your typical view
model.
Imagine you're there. The users hit a button. You've done some processing and then
you want to navigate, right? So you've got a navigation service. And you want to go to
another page, let's say.
What does that navigation call look like? Do you like view first where you say, hey, I
want to navigate to a page type, very much like with the frame navigation service -sorry. The current frames navigation service provides you. Anybody a fan of that?
Anybody like that? A couple people.
Anybody like the second approach, where you actually do kind of a view model first
approach? In this case you can see I'm creating the instance of the view model,
initializing it with some information and navigating to the view model instance. Anybody
like that? Okay.
So a 10-10 split. That's what we found too when we asked our advisors, when we
asked our team, we were kind of divided, you know, which one looks best to us. And
there's some downsides with both approaches, right? With the view first we realize that,
you know, what, I'm not sure if we want our view models knowing about views. We saw
that as kind of coupling that we didn't like.
The second approach, well, in this case the view model knows about another view
model. Should that really happen? What if we have separated teams and, let's say
you're working on a view model and I've got another view model? Should my view
model know about yours? I'm not sure if we should.
So we wanted a little bit of a decoupling there. So we went with a string based
navigation. So here I'm just going to navigate to an item detail experience. Something
else with resolve that experience to a page type. And whatever the navigation
underlying needs, and I'll pass it whatever it param's, right? So that's what we went with
our framework.
All right. The next thing is to use the bindable base. Now, this isn't specific to view
models. But bindable base can be found very, very important. If you're doing any type
of a binding, you're going to need to use INPC, I notify property changed, right? You're
going to need to tell your views that, hey, something's changed. Go ahead and update
yourself. Have the control. Go and get new data. So that's going to be really important
to you.
So bindable basis is provided to you out of the box. File a new project, you're going to
get bindable base, right? We liked it. We didn't see a lot of changes in it, so we just
went ahead and incorporated it into our library.
So you'll get one if you do file new project and you'll also see that we have a bindable
base in our framework. All right.
So what does that give you? Well, number one, it gives you this method called set
property. Set property is really nice. Because typically in your view model you have,
let's say, a property, you have a setter and a getter or getter and setter. Your setter
would typically check the value of the value coming in. If it's different than the value you
already have, then you want to set it and raise it again, right? Only when it's changed.
So that's what this does for you right here. So you don't have to check anymore. This
will only fire the event if it's changed. So you can see here if it's the same we just go
and return. And then it will raise the on property changed method for you.
And you don't have to pass it a string representation of the name of the property. It all
takes -- it all makes the code much simpler. Okay?
So this is provided for you. Now, let's imagine that you have an app and you want to
use view models. But you're in a view first type world, which is in the store. You have
views that you navigated to. But now you have to have view models to support the
views. So how do you do that? How do you have these two things work together?
Well, we're using the view model locator pattern. Now, people have used this pattern
before. Anybody use this pattern before? Okay. It's pretty standard if you've got views
and view models. You need to connect them somehow.
Oftentimes you would have something really simple like you've got a view and you set
the data context of the view to static property of some view model locator class and then
that property would go in to construct whatever you needed to set it to the data context,
right? So that's the general functionality of the view model locator.
What we decided to do here is bring that up a level and make it more general and more
reusable for you. So what we do here is we do a convention based lookup. Imagine
your page is called my page, and you use our view model locator. It's going to go and
look for a my page view model, construct it, and set it into the data context, right? Isn't
that what you need? That's what you'd expect, right?
So we do that for you. So all you have to do is set this attached property here, view
model locator.auto wire view model equal to true at your page, and we'll go and find the
view model for you, assuming that it fits that convention.
Now, what happens if you don't follow that convention? Well, then you're screwed. No,
I'm kidding. Then you can change it. We completely give you -- we have like three
different hooks, three different ways to change that convention. You can simply say, no,
it's actually a different folder, oh, we want to use a completely different way to wire it up.
I'll show you a couple different ways in our talk today of how you can change that
convention.
But out of the box you get a convention. So it will find a view model for you, assuming
it's in the right place. And it will do it up. Okay?
Next thing, validation. What did validation look like back in WPF and Silverlight? Well,
you typically implemented I notify data error info. That was your friend. That was what
you did 9 times out of 10. Your model classes would implement that and then on your
controls you'd use notify validation error true. And then all of a sudden your control
would light up just as easy as that.
For example, here, notify on validation error equal true as well as validates on exception
equals true. So if the code had an exception or had any validation problems, this text
box would light up. Isn't that great?
Unfortunately that's now how it works in the Windows Store apps. You don't have that
support. You don't have those controls that listen for those interfaces or the events that
those interfaces imply. So what do you do?
Our recommendation is to use our validatable bindable base. Validatable, I'm not sure if
that's really a word, but hopefully our ethics team doesn't kill me on this. But, yeah, it's
a bindable base that we saw before. But it's a validatable version.
So how do you use it? Well, you take your model class, for example address here, you
just simply extend validatable bindable base. You can see here in the center we call set
property, as you would normally, right, I mentioned before bindable base provides with
you a set property method. Use it. It's going to be very valuable. It's only going to raise
the property change event if it's changed and so forth. It's very useful.
In this case, set property is not only going to set it and raise the event, it's actually going
to do the validation if the values changed. So your view model code or your model code
doesn't have to change its looks hardly at all. All they have to do is extend our
validatable bindable base.
And then what do you get? Well, you get a property. You can see here in the view you
got a text box. The text is bound to add just that first name. For example here that first
name property. We have an attached behavior. This is just -- this doesn't ship with the
library. It ships in our reference implementation, our sample project, our sample app.
But the highlight form on errors is basically an attached property that binds to the
model's error's property. So model's errors is a collection and I index into it using a first
name, and basically this says, hey, is there anything here? Is there anything in that
collection? If there is anything in that collection, I want to make this control that I'm
attached to highlighted. I want to make it red, right? So that's how that works.
So all that does -- and you can create your own. You can style it however you want.
But this is the point is that what we provide for you in validatable bindable base is a
slightly different set property method as well as the errors property here. Okay?
Question?
>>: [inaudible] extra block or [inaudible] to show [inaudible].
>> Francis Cheung: In this case -- the question was did we need another control to
show the error message? In this case, yes, if you want to show the error message
here. In this case, what we're doing here is we're highlighting if we want -- if this field
here is an error. If you want to show the actual method itself, I'll put that in another text
box. And then in that case, the text box text property would be bound to the address
dot errors first name. All right?
In that case it would show -- it would probably show the first one or so. Okay? Any
questions about this? Again, this is something that's really missing -- you got a question
back there. But ->>: [inaudible].
>> Francis Cheung: Yes. The error message? Yes.
>>: [inaudible].
>> Francis Cheung: Okay. So to localize that, probably the best thing to do is look at
the code. What you can do here is you specify in the data the attribute, the error
message type that you want to use and so you create like a kind of an error message
helper class that has static properties on it. And the getters of the property would call
your resource library. So that's how we've done it. So that's how you would localize
that.
All right. Decoupled eventing. So, again, doesn't sound like we had a lot of fans here of
event aggregator, but let me describe to you what the scenario is here. Imagine that
you have a page and you've got a user control on the page. Well, the page doesn't
have a lot of connection with the user control. All you see is little XAML reference to the
user control and that's it, right? Imagine you have view models behind the page and a
view model behind the user control. They don't talk to each other. This is referred to as
the Hollywood parent pattern. Anybody heard of that before? It's kind of crazy.
I actually had a customer come up to me and -- I was on Prism for a very long time. He
said oh, you should use the Hollywood parent pattern. What are you talking about?
Yeah, we do that all the time in Prism. Like, wow, I had no idea people actually gave
names to this thing.
But it's where the parent really doesn't know anything about its children. Okay? So in
this case, the parent page doesn't really know much about its children. It doesn't
participate in the children's wire up much, except for the fact that it's there in XAML. But
when the parent page goes away, does it tell its children? No. When it gets
instantiated, does it tell its children? Not really.
So the only hookup is in XAML. So imagine you have user control. It's got a view
model behind it -- or let's say it's just got code behind. And it needs to listen to an
event. Let's say you've got long running service. And it hooks up to an event on the
service. All right?
Now, let's say you navigate away from the page and you come back a bunch of times.
What happens? Anybody? Come on. It's a memory leak. It's a memory leak.
Because the user control did the plus equals on the event. But it didn't do the minus
equals. It's connect to go a long running service that will run for the lifetime of your app
and it has you keep running your app, keep hitting that page and leaving it, you get
more and more handlers to that event. But does the user know that? No. So you get a
memory leak. So this is where it's useful to have something that's decoupled. Because
in that user control you don't have an opportunity. You don't have an on navigated
from. You don't have an on closing type of thing to tell you that, hey, this is the
opportunity to close and unregister. You don't have that.
So what we suggest to you in this case is to use our event aggregator, which has -we've referenced eventing. So we ported the event aggregator from Prism into a
portable class library. And we suggest you use that. So here's how it looks if you're
using the events aggregator.
So, for example you've got a view model that wants to subscribe to an event. You
basically take as a constructor dependency the event aggregator here. We call get
event of a strongly typed event there, and we subscribe to it passing it a delegate of
what should happen if the event were to be called.
Here, down here is the case where you publish the event. So, again, you take the event
aggregator reference and at the appropriate time you call publish on the event passing it
a payload. Right?
So that's how you fire the event. That's how you listen to the event. When you do this,
the listener of the event can go away. If that isn't a user control, it can just go away. It
can get garbage collected. It will happen without having to create any memory leaks.
All right? Any questions on that?
So next let's talk about commanding. Does anybody use commands? Coupled? If you
don't use commands, what do you do? You just handle on click on everything? What
do you guys use? Anybody?
>>: [inaudible].
>> Francis Cheung: Okay. So commands are pretty useful, right? Commands are for
really buttons, right? Right now the only control that supports commands is button
base. So if you have something where you want to execute functionality but maybe
only in certain scenarios, for example if you have something selected, oh, then you want
to highlight the button. The button should be enabled when something is selected.
If nothing's selected, well, you want the button grayed out. How do you do that? You
do that through commands. So if you just handle on click of everything will get clicked
and then, you know, you're going to need to tell the user somehow that, hey, you
shouldn't have done that.
But here ICommand provides execute, can execute, and an event called can execute
changed. Those, again, are for those situations where your app state really want -really should affect the functionality or the can executedness of the button. Right?
So, again, those are supported by a button base. There's a whole bunch of things,
however, that you don't get a command -- that commands aren't really adaptable for.
For example, a grid view, right? Let's say you've got a grid view and let's say you -somebody clicks on a certain item and you put grid view. And you want to navigate, all
right?
Well, in that case you get an event. You don't get -- grid views aren't compatible with
commands. So what do you do there? In that case, there isn't this concept of can
executedness, right? It's always executable. If you see it, you can click on it. In that
case, we really just want to get rid of all the stuff and just go from an event to an action.
So that's what we recommend. If you have a button, then you probably want to use
Icommands, otherwise you want to use event.
Let me show you what that looks like. So here's our delegate command. It's our own
implementation of Icommand. It's really, really simple. All you do is you pass it -- you
could see here. We created a new instance of -- all you do is you pass it to the
delegate. The delegate to be executed. The button is enabled you hit it, that method
will get executed.
And then a method for -- or delegate for can execute. So first thing is page is going to
do is it's going to call that method. It can execute and say, hey, can I run you? If so, I'm
going to enable the button. If I can't, it's going to be in a grid form.
And then in the view model you're going to want to raise you can execute change. In
the case where let's say your view models in a state where you really can't -- you don't
want the user to perform that function. So you want to -- you want this method to return
false and then you call that method. Okay?
And simply in your view model you just bind to that command. Pretty straightforward?
All right. So pretty standard stuff. What we're providing here is the delegate command.
Because, otherwise, you'd have to create your own implementation of Icommand. Here,
this is just a really simple way to do it. And it's all the -- all the interface requires is the
execute and can execute, and so we did that all for you. All you have to do is provide it
to the delegates. So people found that very useful. So reported that to the Windows
Store.
Next thing attached behaviors for the rest. For example, I mentioned before you've got
a grid view, right in and you've got a clicked event. So all we do here is we've created
our own little attach behavior. Again, that's the theme. We don't really have behavior
key, so you're going to have to create your own attached behavior.
We set the action equal to that so that this attached behavior listens to the clicked
event. And when it happens, we're going to call that action. Right? And your view
model here is the action is just pointing to a method. So it's just a delegate. All right?
Any questions? All right. Suspend, resume, terminate. Anybody here support
suspend, resume, terminate your app? Okay. You guys all should. Okay? If you guys
get through a certification without this functionality, well that's unfortunate. Because this
is -- should be something that should be tested thoroughly. And that's an experience
where you start up your app, and let's say you swipe away. You launch another app,
right? So you go into suspended state.
If you have enough memory pressure or system resource pressure your app will get
terminated. Your app is not going to know that. It's just going to get removed from
memory. And then if the user decides, hey, I want to go back to my app, so if I find it's
not there anymore, your icon doesn't launch it, it should return to the same state as you
left it, as I showed you in the demo. You need to return to the same state, otherwise the
user says, oh, shoot, what happened to my data? Wasn't I like halfway through filling
out this form? Where did it all go? You need to be able to support that, okay?
So how do you do this? This is really important. And it needs to be handled. What we
do is we provide some support for you if you're doing view models. If you're doing code
behind type stuff, as I mentioned before in your layout aware page, your visual state
aware page, you have the load state and save state methods, you can use those too.
But if you're using view models to store your state, which is, in this case, for example
your form fields were probably bound to properties on your view model, you'll want to
use the restorable state attribute, okay? All you need to do is extend view model, our
base view model class, and put this restorable state attribute. That's it. The framework
does the rest. If your application is -- is terminated or actually is suspended, because
we don't know if you're terminated. If you're suspended that's the only opportunity that
we have to stash away any state. Termination you're not going to get an event. So we
need to stash it away when we can. We need to do it quick.
So what we do is we look at anything with a restorable state attribute, and we put it
away. It's the same -- we use the same backing store as the -- as the visual state
aware page, it use this thing called the suspension manager, right?
So we like suspension manager. We like the functionality. But we didn't like the fact
that it was -- it was static. So we just created a different service that was basically a
copy of the guts of it. So instead of suspension manager we have session state
service. Okay.
So the session state service basically takes all that data, sessions its away for you so
that when you come back from suspension, it goes and rehydrates everything. Okay?
So that's all you got to do.
Unit testing. Anybody do be unit testing here?
Got a question.
>>: [inaudible].
>> >> Francis Cheung: You can. You can -- so the question here is can you include
complex types? So in the previous case I actually had restorable state on a string.
What if my restorable state was on an address, right, or something more complex?
Yes, you can. But ->>: [inaudible].
>> Francis Cheung: Noun types? I'm. I'm not following.
>>: You need to access known types?
>> Francis Cheung: Known types. Yes. Yes. So the question was what if you use
complex types here for the restorable state attribute? Yes, that works. But underlying,
we are using the suspension manager, which was underneath it, it was using the data
contract serializer. So it needs to know what types it is expected to serialize and to use
serialize. So because of that, you have to tell it.
So I'll show you how to do that -- actually, go ahead and take a look at the RI, our
reference implementation, as to how, as to how did we do that? But it's pretty
straightforward to -- we actually have a -- if you look at our MVVM app base, there's an
-- there's a virtual method to provide those known types. But, yes, you have to tell it the
types that you want to serialize. Okay? Thanks for the question. All right.
Unit testing. Anybody doing unit testing here? Come on. You got a -- should have
more hands than that. So unit testing support in Windows Store apps is really good.
Especially if you've been doing Windows Phone type apps. Really the best option out
there was Silverlight test framework by Jeff Wilcox. It was really nice. But the problem
is that it ran the tests on the device.
Well, it was great. You know that the tests are actually running on the hardware that
our expecting. But how do you get the test off? If you get a test failure, how do you
know? How do you report to your build server? How is anybody going to know, right?
You want some sort of automated process that will tell you success or failure. You don't
want to have your developers be in charge of, oh, they get checked in code. I'm going
to go home now. You know. I hope everything went well. You don't want that case.
You want some sort of automated build process to run your test, harvest the results
aggregate them all.
So the unit test framework within Visual Studio 2012, for Windows Store apps is really
nice. So that -- so that's -- that's that point.
Here I provided you a MS build script to extract the contents of the unit test into your
build server. So you can see here I have an item group for the appxs. Here what we're
going to do is we're going to use VStest.console EXE against all of your appx packages.
It's going to run it. And it's going to use slash logger:trx. So it's going to be to log in
TRX format.
So if you use this MS build, you'll go and run those tests and export them as TRX. So
you can harvest them into your build server. Okay?
All right. The last hint here I think is the most valuable. So I already talked about
flyouts. So in order to create a flyout, it's probably -- well, I think the sample, if you look
at the sample, it's like 50 lines of code in order to create a flyout. That's not talking
about the actual flyout itself, the XAML to -- with all the controls. Just to create a flyout,
show it, listen to the closed event and do all the wiring, it's about 50 lines of code.
Anybody use Callisto? A person. Okay. So a couple people. All right. So that's Tim
Heuer's project. He created something that will help with that. So he got from it 30 lines
of code -- 50 lines of code down to about 30. But still quite a bit of work.
So what we recommend is to use our flyout view. So all you have to do to do that is
simply take your view class, in this case I created a login flyout. You can see the
picture of it over there. And we're extending flyout view instead of page, right? So all
you got to do is right click new item, blank page, or whatever page you want, typically
blank because you really don't have that -- you don't want that many controls in your
flyouts. Right.
Instead of extend page, you extend flyout view. At a constructor you specify the width.
So there's two standard widths for flyouts, a wide and narrow. In this case it's narrow.
Call the initialized component.
And then, for example, if you want to show it, you just use the flyoutservice.showflyout
and you pass it the name. Similar conventions as I've talked about before. So log in
here. What it's going to do is it's going to look in the view's folder for file for a type that's
flyout name flyout. So in this case, it's going to look for a login flyout. Okay? That's all
you got to do.
And in your page, you put your XAML controls as you expect. The flyout view does all
the ugly work for you. The ugly work of creating the popup, taking the stuff, putting it as
the child of the popup, listening to the closed event, all that stuff, all the wire-up, the
boilerplate code, it's all taken care of for you. All you have to do is this. Right?
Does that help anybody at all? Got another question.
>>: [inaudible].
>> Francis Cheung: So that the next step. I can show that to you if you want. But this
is just to show the flyout, right. So this is the code to show the flyout. If you want to
include it in the settings, that's just a little bit more code. I'll show you how to do that.
But this is at least how to show the flyout.
The settings charm can do a whole bunch of things, right? You could show flyouts.
You could launch to different URLs, you could do a bunch of things. But this is the code
to actually just launch the flyout. All right. Any questions on this? All right.
Let me create an MVVM app from scratch for you. What we'll do, go over to Visual
Studio, file new project. I'll set with a blank app. I'll call this AppXfest. All right. And
what I'll do is I'll go ahead and bring in the other project, our library project. Which is
Microsoft.practices.prism.storeapps. We'll probably be shipping this initially as source.
So you probably need to do something similar. Okay? And we'll go ahead and create a
reference to it. All right.
So let's go back to our appfest project here. Let's take a look at the app XAML CS.
What you'll realize here is that you've got a lot of boileplate code. We're listening to the
suspended event in order to hook everything up, right?
So what we'll do is we'll get rid of all the boileplate code. Does that make anybody
happen? Anybody? It makes me happen. Because it's the same code over and over.
And you got to muck witness a little bit in order to get your app to run correctly. If you
don't put things in the right order, it's going to be very unhappy. So get rid of all the that
boilerplate code. Instead of a set application, you would go and expend MVVM app
base. Okay?
And then it complains to me. It's like, oh, well, extending me is fine. But we need to do
a little bit more than that. Let's go ahead and we need to provide it an implementation
of on-launch application. You need to start your application somehow. Typically you
want to navigate to a page, right?
So we'll go ahead and navigate to a page. Let's go ahead and navigate so that there is
a navigation service provided. I'm going to navigate to the start page. Okay? And pass
it in null. And that's almost all you have to do. In this case, you have to go ahead and
update the application here to also extend from MVVM map base. Okay? We can build
it. Should be happy with that. But now what's it going to do?
It's going to try to navigate to a start. Well, we don't have a start page. So let's go
ahead and create that. I'm going to create a folder within my project. I'm going to call it
views.
So my convention -- the navigation service is going to follow the convention that it's
going to look for the view in the view's folder. I can change that convention if I want, but
let's just go ahead and follow it for right now.
In the view's folder I'm going to add new item, a blank page. And I'm going to call it -anybody?
>>: Start.
>> Francis Cheung: Thank you very much. Start page. Right. So that's convention.
So in my start page, I'll go ahead and put in a little text box -- text block over here, just
to make sure that we're in the start page. Text block, all right? And if I run my app
what's it going to do? Oh, there we are. Start. Well, I hit art. But we're pretty close.
So what we've done is we've created an application and navigated. Not that
impressive. But let's take a look at what we have. Let's go back to your apps MLCS.
And in our app let's see what other services we have. We have the navigation services
we've seen before. We have a session state service. And I believe up here we also
have a flyout service.
So we have those three service that we provide to you by the MVVM map base. All you
have to do is extend it, and those three already configured for you. If I want to show a
flyout, I can do so here too.
All right. So let's do that. Let's go ahead and create a flyout. See how painful that is.
I'm going to add a new item here. Blank page. Let's go ahead and call it a login, for
example. Right? Is and let's say -- actually before we go ahead and show the flyout,
let's talk about view models here. So we have our start page.
Now, let's see what it will take to connect the start page to a start page view model.
Let's follow the convention again. Let's go ahead and add a project -- sorry, a folder.
View model, and within that -- again, we have a start page. So what am I going to name
my view model?
>>: [inaudible].
>> Francis Cheung: Thank you. Okay. Move all that stuff.
Okay. Right now I don't even have to extend our view model. Let's just see what
happens here. What I'm going to do is I'm going to create a property. Okay. And
instead of making auto property, let's create a backing field, just so that I could put a
break point right here. Right?
So what we're going to do is we're going to go to your start page and bind to the center
and see if it works. Right? So our start page here I have got a text block here. Let's
put in a stack panel so it doesn't blow up on me. Okay.
Got the text block there, and I'll put a text box here. Text equal binding name -- is that
what I name my property there? I think so. Name property. Okay. So I'm binding this
to name, binding it to make sure that the binding is 2 way so that the view model can
update the view and the view can update the view model. Okay? Run that and see
what happens. See what I did here. All right. Get rid of this. See what happens. See
if I hit that.
So we're at a start page here. I put some data here. I hit tab. Nothing. Hmm. It's
because our view and view model aren't connected yet. So what we have to do is in our
start page in the XAML for the page what I do here is add
viewmodellocator.autowiremodel equals true. Let's try that now.
So now, when the page loads, that property is going to hunt for the according view
model in the typical place. If it fine it, it's going to call -- activate or create instance on it
and put into it the context? Right? So now I've got my view model -- I've got my view
here, some data here. Hit the tab. And here we have -- we've hit the center. So here
we've connected the view model to the view with minimal, minimal pain. Right? So that
worked fine. But now say I want to do something more interesting to my view model.
Notice the view model is pretty simple. And the state I just made about 10 seconds
ago, the fact that our view model locator calls activate or create instance, does anybody
think that's kind of strange? Normally you wouldn't do that, right? Because your view
models typically have dependencies. And these dependencies typically shown as
constructor parameters. Right?
So let's say this view model now wants to do something with the flyout. If you hit the
button, imagine you've got a button here and you want to show a flyout. Let's do that.
Okay. So let's first create a command here. I forget I have a mouse.
Let's call it show flyout command all right. So I'm a constructor. I'll go show flyout
command equals new delegate command. So here let's say I just want to do a show
flyout method. Right in here I'll just go ahead and create the method here. All right.
And so we've got this command. I'll go ahead and hook up a button to that. So my start
page I'll go ahead and put that right blow the text box here. Button. Let's go text. Is it
content? I forget. Content. Yeah. Show flyout, right. Command equal a bind to the
show flyout command there.
All right. Let's see if I hit my break point. Hit the button. And I hit my break point, right?
So that's all you need is to do to set up a connect buttons with commands. So here all
they did is create the delegate command there, pass in a delegate of what I want to
execute, so that's the show flyout here. And I hit my break point. Groovy. No big deal
there.
But now I actually want to show the flyout, right? I want to show that flyout that I spent
all the that time creating, right? So actually let me do something on the flyout just so we
can see it in action. The login flyout here I'll go ahead and put in a little text here, text
box texts.
All right. Just so if it shows up, it shows up. And actually, let's make the background of
this instead of that static resources, let's make it white. Anybody know why? Turns out
there's a UX guideline for this. Flyouts have to have a white background. Have to have
a light background.
So even if your app has a bark theme, which most do, because that's the template, your
flyouts have to be a light background. Which great. You are know why? Because that
means all of your controls need to be restyled for your flyouts. So if you put any
controls over there, you need to provide a light theme style for all your controls.
So it's a little bit of pain point. But just to let you know. I'm not sure if they'll catch it in
terms of the review process, but if you read the UI guidelines, they have to be a light
background. All right? So now you'll see that. All right.
So now our view model here, what we want to do here is we want to do something like a
flyoutservice. -- actually it would be something like flyoutservice.showflyout and we want
to show the login flyout, right?
But this is a service that we don't have access to right now. What we want to do is we
want to get that service passed into my view model. How do I do that? Well, we
typically make that a constructed parameter. Okay? All right. So now I've got my
variable. There it is. Great.
If I hit a five, what happens? Kaboom. Right? Activate or create instance on
something that does not have a default constructor is not going to be happy. So what
we need to do is we need to help the view model locator resolve that dependency.
So there's a couple ways of doing it. We can either take the more explicit way, where
we actually tell it -- tell the view model locator, hey, if you run into this view and you
need to create its view model, here are specific instructions, here is the delegate that
will return you the theme that's set in the data context. Okay? That's option number
one.
Option number two is use a dependency injection container. In the dependency
injection -- anybody use Unity or any other dependency injection containers? One?
Come on. More than that. No? Right. So this is pretty standard in business in
enterprise applications. Dependency injection containers are very common because it
gives you that decoupled experience. So you don't have to know about the actual
implementation of any service. You're just programming to interfaces. You don't know
about the specifics of any service. You only deal with interfaces.
Something else is going to resolve it for you. So here you just specify your
dependencies and say, hey, I need an I Foo service. Please, somebody provide that to
me when I'm running. So that's something else's responsibility.
So we have option number one, which is to do it explicitly, provided factory method to
construct it. Option number two is the container approach. Anybody want to see the
container approach? The explicit approach? All right. I got a couple hands for the
container approach. All right.
So let's say we want to use the Unity container. I like it not only -- not just because
Patterns and Practices wrote it but the Unity container, like a lot of the other containers
out there, they don't require you to change much of your code in order to use it. Right?
Anybody use MEF? Okay. MEF is also a very popular container because it comes out
of blocks. Although for Windows Store apps it's not really out of the box. You still have
a package you have to download. So it's not quite out of the box.
So anyway, here, let's go ahead and take a reference to Unity. So I'm going to right
click on references here. Manage new get packages. And the current version of Unity
that is compatible with Windows Store is not in release yet. So let's go online. Here I
include pre-release.
I must not be online. I'm not online. That's not good. In that case I'll just go ahead and
refer to a previous version of Unity that I've used before. But typically you just include
the NuGet package. Anybody here use NuGet? Come on, you guys all should be using
NuGet. All of your dependencies should be resolved through NuGet if at all possible.
I've actually had some cases where somebody wrote a library and they didn't created a
NuGet package. I said, you know what, I'll create you a NuGet package. Your library is
so popular that I don't want to depend on somebody having to download the DLL and
put it in the right folder, I'll just go ahead and create a NuGet package for you. And
whenever you want to take it over, feel free to take it over. But it's so useful.
In your project, you just create these NuGet package dependencies, and your
customers, when they get your source code and they compile all those dependencies
will come down. Even the newest versions will just automatically get downloaded. So
NuGet is a good thing. But in this case, it doesn't look like I have connectivity so I will
just go ahead and take a dependency on the DLL, which I have previously. All right.
And first thing I want to do here in my app is create a member variable. All right. So
here I've got a field -- you probably want to do this in a property. All right. And then
what we want to do is we want to configuring the container with all my services.
So in this case, I really only care about the file service because that's what I'm
depending upon. So what I'll do here is I'll look at the overloads that I've got for MVVM
app base. And you'll notice that there is an on initialize. This is where you want to
initialize your application. On initialize. Okay? Actually let's make sure to include the
base, because there might be something in the base. Okay? So here we'll go
container.register. In this case we're going to register an instance because the MVVM
app base is already configured the file service for you. It's already ready to go.
I just want to register it so that I can resolve it. So I'm going to go register instance of
the flyout service. Right? And the container already can configure out, hey, what
interfaces does this thing implement? And it will go and register it based upon that type.
All right?
And one other thing we have to do, there's a resolve method. Basically we want to have
a type, and I need to return an object. So I'll use the container to do that. So I'll just go
return, container, resolve of that type. That's it. That's all you had to do to configure a
container with your MVVM application.
So now let's try the same thing. Okay. It doesn't blow up. So that means the
constructor was at least resolved correctly. I'll hit the button here. We'll see if I hit the
code. Let's see here. See if I hit that. Okay. I hit that. So now my flyout service
should be called. And the flyout, the login flyout should be shown. Let's see if I spelled
that correctly. So I got my login flyout, login flyout XAML, yeah. Funny. So anyway,
that should have been shown off to the right. The demo gods aren't with me today.
Oh, maybe because of the break point. So let me get rid of the break point and try
again. Anyway, what should happen at that point is the flyout will come out to the right.
Let's see. Oh, sorry. I need to configure the container. I always forget about that. So
when I register the instance in this case, the lifetime manager, I'm going to give it a
container controlled lifetime manager. Basically making this a singleton. Okay. Let's
try that now.
Otherwise when it resolves it, it will try to create a new instance every time. Let's try
that now. All right. I'll figure out what I did wrong and kick myself later.
Any questions about that? All right. So what we did, basically everything we talked
about in the slide deck we created a view. We navigated to the view, connected the
view to view model, put some commands on the view model connected to buttons.
Also, let's do this.
In the start page, let's see here. You notice that the name doesn't have any attributes
on it? So what happens when we start the application? Let's go here. Put some data
here. And I go here and that -- let's try that again. Put some data here. Come back to
the app. Oh, that's right. Break point. Thank you. All right. And let's say we terminate
the application. Go back in. Oh, where's our data? Let's make sure that's restorable.
All we do in our view model is extend the view model base and put an attribute on this
guy. Restorable state. Put some other data in it. Go back to VS. Shut down. Run the
app. And our data's preserved. Right? That's pretty useful, especially if you're doing
forms over data. That's not necessarily the only thing you're going to be concerned with
when you're doing business style applications but that's definitely one of them.
All right. Any questions about that so far? No? I'm that good. No, I can't be that good.
All right. So that was creating the app from scratch. Any last questions? Got a
question back there.
>>: [inaudible] pop up because you're not online right now?
>> Francis Cheung: No. It's nothing that it should be getting. So I'm not sure why it
didn't show up. But I'm sure I just fat fingered something.
But go ahead and take a look at the RI. Everything is working there.
So any other questions.
>>: I have a question [inaudible].
>> Francis Cheung: Okay.
>>: How does that -- you know [inaudible] the current view model. So assume they've
[inaudible] in memory but not [inaudible] on this page. Would that catch the data --
>> Francis Cheung: Okay. So the question is how does a restorable state service
work. And you mentioned another view model in memory. But typically view models
that are connected to pages go out of memory. Unless you tell the page explicitly to
cache itself.
So let's say you don't cache the pages. When you go from page A to page B, page B's
view model will be loaded, page A's view model will go away. That's typically what
happens.
>>: So [inaudible] cache assume that you don't have to create a view model [inaudible]
know that I'm going to be using data. So is it best practice to do that on -- you
mentioned that [inaudible] use the vehicle to describe your model. Is that.
>> Francis Cheung: So if you're doing -- so the question was what's best practice
around where to store your state, I think. So I think -- let me see if I could answer this
question. If you're doing view model type work, MVVM type work, your fields, your
model will be in your view model.
The only state that your view will know about is things like scroll position. You typically
wouldn't want to store that in injure view model. That's not really business. That's just
kind of UI state.
All the other state, like the values, the form fields that user entered, you want to store
that. And they eventually want to go into the back-end services, right? So you typically
have them defined in your view model.
So the view model state you definitely don't want to lose. So you want to use a
restorable state attribute on those types of fields. Did I answer your question?
>>: Kind of [inaudible]. Okay. Let [inaudible] my question. So if I have a page I have
to control and each control has its own view model so it goes to automatically
[inaudible].
>> Francis Cheung: So the question was really around composability. Imagine you
have a page. Let's say the page has a view model and it has two user controls on the
page and those have different view models. That is actually the exact scenario that we
had in the check out hub page where you saw the shipping, billing, and payment. That's
exactly that same case.
So in that case, the Hollywood parent pattern doesn't work very well, because we need
for the parent view model to pass down the information. Because the parent view
model knows that, hey, I'm navigating away from them. So that's the -- that's a good
time for me to tell my children, hey, I'm being navigated away from.
So in that case, there is a little bit of wire-up code to coordinate the relationship between
the parent and the child controls.
>>: [inaudible].
>> Francis Cheung: Yes. So the question is, you know, how do we make sure that
happens? In the case where you have a composition type model where you're not just
exposing the fields or the properties on the view model, you actually have view models
or the page's children's view models that you want to coordinate the -- the closely
connected pattern is better.
So the parent view model knows that, hey, I'm being navigated away from. So I better
call my children's unnavigated from. And his children need to call its unnavigated from.
That's the only way I think it will work. Okay?
Question over there.
>>: I have two questions. First one is also related to the lifetime of the view model. So
what if we want to tell our vacuum that persists across the multiple [inaudible] is there a
way to do that?
>> Francis Cheung: A long live view model?
>>: For example, I have a form -- view model that gives me a lot of fields and there are
multiple pages to fill out all that.
>> Francis Cheung: So the question is what do you do with a view model that lives
longer than one page, for example a wizard. You may have a wizard that fills out part of
the form or part of the view model on one page, and it continues to fill it out. In that
case, I don't see it as a view model. That's really more of a model, right? You've got
this big model thing that eventually will get filled, and then you need to take that thing
and submit it to back in service.
So in that case, what I would do is I would have the view models go and fetch that
model thing, that long live model thing from the service that is long lived. Typically what
I've seen on the wild is that the view models are really the models for a view. Right?
So if you got five things on the view, the view model helps support that.
So you typically have those five things exposed as properties of your view model.
Typically not more. Now, in your case, what I would say is I would ever the view model
say, hey, I'm concerned about the shipping address part of the model. So in that case,
you would go and call some back-end service and say, do I -- what is the current
shipping address for this user. And I would go and pull it. Then I would paint those
fields on the screen.
And then the next screen it would have its view model, it would get other fields. So in
that case, I wouldn't have this long lived view model, it's more the model thing that
spans the whole lifetime of the wizard. That's what I would do.
Do you have another question?
>>: The question was [inaudible].
>> Francis Cheung: So the question is this available for C++ right now? No. This is
just meant for managed code right now. Mainly because my customers who are doing
more of the line of misses type applications are using C#. But I think a lot of these
concepts can be ported over to C++. Especially over to the XAML stack. A lot of these
things still pertain.
Question?
>>: So following on the note, taking the extensive knowledge that you have [inaudible]
line of business, but say a lot of the guys here are not looking at long business apps, I'm
going to actually talk about his app, I forget the name of it, wizard app, considering he
got a lot of content of stuff like that, if he wanted to take features and compose what
you're presenting, how applicable would that be for someone who is not [inaudible] his
application?
>> Francis Cheung: So the question is how applicable is this code, this guidance to
apps that are not necessarily line of business? I think it's highly applicable.
If you want your app to be refactorable, well, how do you know that your app is
refactorable? To me the only way -- what that translates to me is unit test. Do we have
unit tests that will ensure that, hey, if I change this one line of code, does it break the
app? How are you going to know?
So if you want to have any level of quality where you expect a certain level of
maintainability across say a team of developers, I think you need to make it testable.
So therefore MVVM is the typical pattern to provide that testability. So I think it's very
important. I know some people who do unit tests, even TDD all by themselves in a
room. They have no other developers, you know. And they're even using them on
spike code.
So I think if you cautious if I care about testability and the ongoing maintainability of
your app, I think it's very applicable.
>>: [inaudible] I know when [inaudible] a lot of new people that come to this event for
the first time. And the little sample [inaudible] that you demoed how to show [inaudible]
group containers. So if I'm just starting with a Windows 8 app and I start with a great
app which has all of the [inaudible] how can you take from the Vis Studio and create
template app to kind of using some of your stuff and help people visualize it? Are you
guys going to have guidance for that?
Because, again, you're talking about a line of business, but a [inaudible] saying, hey, I
want to do a reader app or book app or [inaudible] app or video app, and I may want to
take some of the same guidance. But they don't start with the grid app. So how do you
see them using your stuff so it's not too complicated for them and complex? But do you
guys have guidance on that ->> Francis Cheung: All right. Thanks for the question. The question is around how do
you take the guidance here and the code and adapt it to projects other than the blank
project, which is what I showed here.
I think the answer is that it's very applicable. The only difference to me in the grid
template versus the blank template are the views. They give you a couple extra files. I
think the bindable base and the outlayer page only show up if you ask for some of the
advanced templates. But really it's just the views. So with the exception of XAML, this
is all applicable.
So the thing that I showed you in the boilerplate code in your app XAML CS, that should
all go away, same as in the base -- in the blank template. It should all go away as
boilerplate code. And what you really want to do is you want to add your business
specific initialization logic or registering of known types logic, all of your business
specific application logic, that's what you should expect to see there. So it should all be
the same. The only difference is the views, right?
So the views need to get the data from somewhere. In the case of the new projects, it
gets it from some mocked out services in the [inaudible] behind. You could easily swap
that out for a view model. So I think it's easily applicable. Any other questions?
>>: [inaudible] can you use for the existing app? [inaudible]. For example, we have 10
pages [inaudible] is it something I can use this framework [inaudible].
>> Francis Cheung: Okay. So the question is how hard would it be or how easy it
would be to adapt this code to an existing application? And I think the question -- I think
the answer to the question is it should be pretty easy. But as you can see here that I
provide a lot of base classes, okay, for example, the base view model, base flyout view,
a lot of base functionality. We try to encourage -- we try to adopt composition over
inheritance. But in this case, we just got so much bang for the buck if we inherited that
we decided to do that. That makes it a little bit harder if you have your own base
classes.
But we shipped the source. So if you like our functionality you can take the code that
you want and put into it your base classes. Also, the functionality that I showed you
was really quite separate. The validation logic doesn't depend on anything else. If you
want validation, you just extend validatable bindable base, and you just bind to the
errors collection. That's all you have to do.
If you want the restorable state attribute, that's a little more involved, because restorable
state needs to know if you're being suspended. So in that case we need to have the
view model base as well as the frame navigation service. Because the frame navigation
service is telling -- is what tells the view model, hey, I am leaving you, so you need to
save your state.
So in general, we try to make the pieces as decoupled as possible. So it really
depends. I love to find out if you do try to adapt this to your project how difficult it is.
Because we'd love to hear that feedback back too.
Okay. Any other questions? All right. I want to thank you very much for attending and
spending your time with me today. I know this is your evening. And I appreciate your
time. Thank you very much.
[applause]
Download