Joe White’s Blog

Life, .NET, and Cats


Latest project: a video game in AngularJS

October 14th, 2013

I’ve been playing with AngularJS (“Superheroic JavaScript MVW Framework”) for a while. And, as is my wont, I’m trying to learn it by writing a video game with it.

Here’s an introduction to what I’m doing. I’ll go into more details in the near future.

The video game

I’ve been writing and re-writing the same video game for probably at least ten years now, sometimes in Delphi (with or without DirectX), sometimes in WinForms or XNA or XAML, now in HTML5/JavaScript. (It’s a spare-time project, which means I don’t do it to finish something; I do it to learn something.)

The game I’m trying to write is a 2D console RPG, in the vein of the early Final Fantasy games. I haven’t decided whether I’ll target a Web browser, or a Windows Store app; possibly both. Gameplay will be much like Final Fantasy if it were written with a touchscreen in mind. Artwork will come largely from OpenGameArt, especially the Liberated Pixel Cup-style artwork (including some of my own) and the Universal LPC Spritesheet.

And yes, I’m going to try to do this using Angular. Hey, you don’t really know a tool until you’ve tested its limits, right?

A brief introduction to Angular

Some JavaScript frameworks, like jQuery and Handlebars and Knockout, try to solve one small problem and solve it well. Angular, on the other hand, tries to do it all — everything from templating to two-way databinding to extending HTML to dependency injection to testing. And it does it all with relatively few mechanisms — you’ve got services for shared code, directives for manipulating the DOM, and controllers/scopes, and that’s about it.

One nice perk is that Angular uses Jasmine for testing, which means you get those beautiful nested describes. God, I wish I could do that in .NET for my day job.

Angular has a fairly steep learning curve, so I’m not going to cover the mechanics here. The Angular web site has good documentation, including a tutorial. There’s also some good stuff on YouTube, and I picked up a copy of “Mastering Web Application Development with AngularJS”, which is pretty decent.

angular-seed

The angular-seed project looks like it’s probably the best starting point for writing a generic Angular app. Sure, you could start from zero and reference Angular via CDN, but angular-seed gives you a few niceties like a local Web server (node scripts/web-server.js), and it comes pre-configured for you to be able to run your tests (scripts\test.bat) — in watch mode, yet, so they automatically re-run whenever you save one of your source files. Pretty nice.

(There are other starting-point projects out there too, so if you want something with Bootstrap already baked in, or a Node.js/Express backend, there may already be something better than angular-seed for you. But I don’t want any of that stuff, so angular-seed is great for me.)

My only real complaint about angular-seed is that it doesn’t have any Grunt support built-in. It’d be nice to at least have a Grunt task to run the tests, especially since Grunt doesn’t look nearly as easy to get started with as something like Rake. But otherwise, angular-seed seems to be a great jumping-off point.

So… Angular for a video game? Really?

I don’t know whether it would be practical for the overland map, but I think Angular has some potential for the battle screen. There’s a lot of state management that would work well with an MV* framework, like showing a hero’s menu when it’s his turn. And the upcoming Angular 1.2 has some nice support for CSS3 animations — and there are a lot of little animations during a battle: hero takes a step forward, swings his sword, bad guy flinches from the hit, damage numbers appear, etc. I think I can make all those animations happen with databinding — which would mean it’d all be just as testable as I wanted it to be.

Of course, if you’re just using the built-in databinding, then Angular doesn’t tell you when the animation is done so you can start the next one. But Angular is extensible, and if you write your own directive, you can get those notifications easily. I’ve been working on an animation queue to coordinate all these animations across different scopes and elements, and it’ll be interesting to see if I can pull it off.

What’s next?

Angular-seed gives you a workable start. But to be honest, it’s not really a comfortable environment, at least not right out of the box. In particular, Jasmine tests are much nicer in CoffeeScript than they are in JavaScript. And you need a good way to see whether your tests are passing or failing. More on those next time.

Stefan White, 1998-2013

April 22nd, 2013

Our oldest cat, Stefan, died this morning. It was sudden. Yesterday he was outside, lying in the grass, happy as can be. This morning, he woke us up at 4:30, yowling over and over. We got him to the emergency vet, and probably within five or ten minutes of us getting there, he was gone. The vet said it was probably a stroke.

We got him the second year we were married. The small company I was working for hit some rough times, and we had to move into a smaller apartment — but one that allowed cats. When we went to the shelter, they showed us the cats that were up for adoption, and told us they had one more in the playroom, drying off; he’d just had a bath. We asked to see him, and this little gray tabby jumped, soaking wet and purring up a storm, into Jennie’s arms. She called me over, and he walked out onto my outstretched arm, and perched there and purred. So it wasn’t like we had much choice; he picked us. He was about a year old then, lean and rangy enough to balance on my arm.

We couldn’t take him home that day (I don’t remember why), so they put him back in the playroom. The door was one of those with a tall, narrow window up high; and Stefan jumped up, hung by his claws from the bottom of the window, and meowed piteously. It was hard to leave him.

He was always a purr-motor. Scratch him behind the ears for a few seconds and he’d purr for five or ten minutes. Walk past him in the hallway and he’d start purring. And he would come and curl up with us and purr and purr and purr.

He used to play fetch. Jennie would throw her necklace, and he would tear off after it and bring it back. He’d have the chain in his mouth, dragging the necklace behind him. He would lay his ears down sideways as he dragged it, kind of like we might make a funny face if we were carrying something heavy. One time he jumped down off the second-floor landing to chase the necklace. He was fine, but we were a little more careful where we threw it after that.

That apartment had a shared laundry area, and we would let Stefan out to prowl the hallways when we did laundry. He loved to explore. More than once, he wandered into a neighbor’s apartment to make friends.

Later, we moved to a rental house with an unfinished basement — more of a cave, really; the ceiling was only about five feet high, so it was no good for anything except maybe storage. We used to let him prowl down there, and he’d come back with cobwebs in his whiskers and ears. One night he woke us up with a gift of half a dead mouse. We kept the basement shut after that.

We had a cable guy over one time, and he tried to put a tool back in his toolbelt, only to find that Stefan had curled up in that pouch. Stefan just looked up at him like, “What?”

One time a neighborhood cat got into our screened-in porch, and Stefan was very interested, curious, sniffing at this other cat. The other cat just hissed at him, but Stefan kept on sniffing and trying to be friends. That’s when I realized Stefan was lonely; Jennie and I were both working full-time, and Stefan missed our company. So we went to get him a little brother, and brought home a little orange puff-ball we named Tycho. But unlike the neighborhood cat, this time Stefan was having none of it. We had to keep one of them upstairs and one downstairs, and there was no door in the doorway to the second floor; we had to lean a mattress against the doorway to block it off. (Later they did warm to each other — they would curl up together to nap, or get into fights over who got to give who a bath.)

After we moved to Omaha, and Noel adopted us, Stefan and Noel did not get along; they would fight all the time. That is, until they were on top of the fridge (fighting) and both fell behind it, and were stuck there. This was our spare fridge in the spare bedroom (so at least they fell onto carpet) and we had to move some furniture around to get them out, which included moving books off bookshelves, so it took us a while. But evidently the time in close quarters did them some good; they got along much better after that.

The first time we took him to the vet in Omaha, when the vet came into the exam room, Stefan purred and hissed at the same time, while he twirled lovingly around her legs. She laughed and called him a twit.

After we bought a house, we started letting the cats out to enjoy the weather in the back yard. Stefan liked to eat grass, and then would usually come back inside and throw it back up (generally on the carpet, naturally). But he loved being outside; he would lie there, basking in the sun, or else sitting under the tree, listening to the birds, his nose twitching at everything there was to smell.

Jennie’s computer used to be on the floor of her office, and he would come and curl up on the floor between her and the keyboard, purring mightily. She would play music on the computer, and whenever “Who Will Shoe My Pretty Foot?” came on, she would sing along and tickle his feet, and he would grumble and pull his feet away and keep right on purring.

He went to the vet for a checkup last Thursday. He’s been overweight for years now, and he had bladder stones a few months ago, so they did an ultrasound on him to check on his heart and his bladder. They gave him a clean bill of health. They also removed some teeth that had been giving him trouble. Whatever anesthetic they gave him, it must have been good stuff, because after we got him home, he purred nonstop for the rest of the day.

Just yesterday, he was lying out in the grass, happy as could be.

The vet this morning said there was nothing we could have done. It sucks that he had to be in pain and scared, but at least it wasn’t for long.

Goodbye, Stefan. We’ll miss you terribly.

Making DataContractSerializer play nice with UpdateControls

January 18th, 2013

I’m really psyched about UpdateControls. I haven’t used it in too many projects yet, but it’s already changing the way I think about INotifyPropertyChanged, and opening new horizons yet unexplored.

(If you’re not familiar with UpdateControls, here’s my intro. tl;dr: If you do MVVM, you want to learn about UpdateControls. And it’s free.)

But UpdateControls just takes care of what happens between your model and your viewmodel and your view. There are other concerns your app has to figure out too, like moving data between your model and some kind of persistent storage. I’m writing a game, so I don’t have a database back-end or a service tier; I just want to save state to a local file. Sounds like a job for DataContractSerializer.

Simple enough, right? I just slap a [DataContract] attribute on my model, [DataMember] on all the public properties, and write it out, no problem. Then I try to load it back in, and… my app promptly crashes with a NullReferenceException. What went wrong?

War of the Constructors

The crux of the problem is that an UpdateControls-based model has to do some initialization in its constructor before you can start using its properties, whereas DataContractSerializer doesn’t acknowledge that the constructor even exists.

Recall that, when you define a model object using UpdateControls, you wrap each of your data fields in an Independent<T> that handles the bottom half of the notification magic. Our model object looks something like this:

[DataContract]
public class FooModel {
    private readonly Independent<bool> _active = new Independent<bool>();
    [DataMember]
    public bool Active {
        get { return _active; }
        set { _active.Value = value; }
    }

Notice that the _active field is initialized to a new instance of Independent<bool>. When this code is compiled, that assignment actually gets inserted at the beginning of the IL for FooModel’s constructor(s).

DataContractSerializer, when it deserializes a stream back into an object, doesn’t call any constructors; it just grabs an empty hunk of memory and calls it an object. I don’t know why it skips the constructors; it makes things awfully weird — as well as making it hard to delegate the property’s storage to another object, like you do with UpdateControls. Since FooModel’s constructor never ran, _active is null; so when the deserializer tries to set the Active property, the _active.Value assignment causes a NullReferenceException.

You can get different behavior by removing the [DataContract] attribute and serializing the object as a Plain Old CLR Object (POCO). If you’re deserializing a POCO, DataContractSerializer actually will call the constructor. But, it won’t serialize sub-objects — for POCOs, it looks like it only operates on properties with primitive types. No good for me — I don’t want to cram my entire application’s state into a single object.

Classic solution: Persistence objects

If I was using Entity Framework, I wouldn’t even be thinking about saving my model objects directly; I’d already have a separate set of entity classes that represent tables in the database. These classes wouldn’t depend on UpdateControls, and I’d have to manually copy the data between my model and my entity objects. Similarly, if I was saving to a service tier in a multi-tier application, I’d have the same situation with data transfer objects: I’d have to copy my model object’s contents to a DTO and back.

I could do the same thing with DataContractSerializer. I could define some persistence classes — dumb data contracts that are only used to save and load — and then copy data between those and my models.

The thing is, that “copy data back and forth” step is (a) hard, (b) boring, and (c) easy to screw up. I strive to be constructively lazy, and hard/boring/easy-to-screw-up is high on my list of things to avoid.

At work, we automate the hard/boring parts (and unit-test the easy-to-screw-up parts) with AutoMapper, which works really well. I think it would play pretty nicely with UpdateControls. But there isn’t (yet?) a WinRT version of AutoMapper, so that won’t help me with my WinRT app.

And even if I could use AutoMapper, it feels redundant to make a whole separate set of classes, with all the same properties as my model objects, unless it’s absolutely required by some persistence framework. Even if AutoMapper was there to remove the grunt work (and warn me when I forget to add a property to my persistence object), creating all those extra classes still feels unnecessary. DataContractSerializer should be able to serialize objects; that’s its job. The only problem is that it doesn’t run any of our initialization code. If that was solvable, we’d be golden.

OnDeserializing

If you poke around the System.Runtime.Serialization namespace, you’ll find the OnDeserializingAttribute.

The documentation for this attribute is pretty vague: it just says that it lets you designate a method to be “called during deserialization of an object”. When during deserialization? Before any fields are deserialized? After all the fields?

But since there’s also an OnDeserializedAttribute, I think I’m fairly safe in guessing that these follow the usual pattern: first the -ing method is called, then some other work (deserializing the object’s properties) is done, then finally the -ed method is called. Assuming that’s true (and I think it is, since my tests are passing), then you can use it to make a constructor stand-in for deserialization.

So you can make these changes:

  1. Add a new method called InitFields.
  2. Remove all the initialization expressions from the field declarations, and move those assignments into InitFields.
  3. Remove the readonly from the fields, since they’re now being assigned in a method, not in the constructor.
  4. Add an OnDeserializing method and tag it with [OnDeserializing], and give it a parameter of type StreamingContext. (I don’t know what the parameter is for, but you get a runtime error if it’s not there.)
  5. Call InitFields from both your constructor and your OnDeserializing method.

If you’re using ReSharper, then you’ll also want to add the JetBrains.Annotations NuGet package, and mark the OnDeserializing method as [UsedImplicitly] so ReSharper doesn’t warn you about the unused parameter.

Et voilà — you now have an UpdateControls-based model that you can serialize and deserialize successfully with DataContractSerializer! Here’s what it looks like:

[DataContract]
public class FooModel {
    private Independent<bool> _active;
    private void InitFields() {
        _active = new Independent<bool>();
    }
    public FooModel() {
        InitFields();
    }
    [OnDeserializing, UsedImplicitly]
    private void OnDeserializing(StreamingContext context) {
        InitFields();
    }
    [DataMember]
    public bool Active { ... }

This works, but it feels a bit clumsy, what with the extra two methods, and the assignments being separated from the field declarations. Just for fun, I decided to see if I could go one better.

Automating the process

Why not make a base class that uses Reflection to find all of our Independent<T> fields, and instantiate them automatically as needed?

My first thought was to plug this logic into both the constructor and OnDeserializing. Here’s what a model would look like in that case:

// Note: this example isn't compatible with the final version of SerializableModel
[DataContract]
public class FooModel : SerializableModel {
    [UsedImplicitly] private readonly Independent<bool> _active;
    [DataMember]
    public bool Active { ... }

If the base constructor instantiates the Independent<T>s for us, then _active doesn’t need an initializer anymore. But then ReSharper’s static analysis warns us that the field is never assigned, and we need to suppress the warning by adding an attribute to tell it that the field is used implicitly (i.e., via Reflection).

I thought I was being clever by removing all the “duplicate code” of Independent<T> instantiation, but ReSharper’s warning was my first hint that no, this really wasn’t technical elegance — it was a code smell. And after playing around with it for a couple of days, I had to agree.

It comes down to cognitive load. Our brains are only so big. When the code does what it says, you don’t have to waste as much of your brain capacity on technical minutiae; you have more brainpower available to actually solve the problems at hand. It’s not worth “removing duplication” if it means the code no longer does what it says. Any time you have to stop and think about where that field is being instantiated, it derails your train of thought.

As an added bonus, doing things this way also means that you can make an existing UpdateControls-based model into a serializable model just by changing its base class, and nothing else:

[DataContract]
public class FooModel : SerializableModel {
    private readonly Independent<bool> _active = new Independent<bool>();
    [DataMember]
    public bool Active { ... }

I like the way this code reads. All the UpdateControls-based stuff looks exactly like you’d expect. The only unusual thing is that you’re descending from SerializableModel, and that’s almost as declarative as the [DataContract] attribute.

One big caution: if you pass a default value to the Independent<T> constructor, that default won’t be used for deserialization. This isn’t a problem in the usual case, where you’re about to load that property’s value from storage. But if you’re reading an older stream that doesn’t contain that property, you might have to figure something out.

Without further ado, here’s the SerializableModel class. This was written for WinRT, but should also work in .NET 4.5. (If you’re using an older version of .NET, the Reflection APIs are totally different.)

[DataContract]
public class SerializableModel
{
    private IEnumerable<TypeInfo> Ancestry
    {
        get
        {
            for (var type = GetType(); type != null; type = type.GetTypeInfo().BaseType)
                yield return type.GetTypeInfo();
        }
    }

    private void CreateIndependentFields()
    {
        var independentFields =
            from type in Ancestry
            from field in type.DeclaredFields
            let fieldType = field.FieldType.GetTypeInfo()
            where fieldType.IsGenericType &&
                  fieldType.GetGenericTypeDefinition() == typeof(Independent<>)
            select field;

        foreach (var field in independentFields)
        {
            var instance = Activator.CreateInstance(field.FieldType);
            field.SetValue(this, instance);
        }
    }
    [OnDeserializing, UsedImplicitly]
    private void OnDeserializing(StreamingContext context)
    {
        CreateIndependentFields();
    }
}

I consider this code to be more of a useful technique than actual copyrighted intellectual property, so feel free to use the above code in any context you wish (no credit necessary). But I’d appreciate hearing about it if you find this useful.

WinRT’s default “save on suspend” isn’t good enough

January 5th, 2013

If you create a new WinRT app, using the templates that ship with Visual Studio (e.g. the Grid App template), the default code will save your app’s state when the app gets suspended.

“Save on suspend” seems like a reasonable model. The trouble is, your app can get killed without ever getting its suspend notification.

If you close a WinRT app (either by pressing Alt+F4, or dragging from the top of the screen to the bottom), Windows switches away from the app immediately, but it actually waits about ten seconds before firing the app’s OnSuspending method. (That “about ten seconds” comes from my own observations of how long it takes until the timestamp changes on the autosave file. That’s on a physical machine, not a VM, so it should be about best-case.)

If, during that ~10-second window after the app gets closed, the user decides to start the app again, then Windows kills the previous instance, flat-out, and starts a new instance. In this case, the previous instance never gets a chance to save.

I suspect (though it’d be tricky to try to confirm) that your app could even get terminated while it’s in the middle of an async save operation — at which point your save file is only partially written, and therefore corrupt, and the user loses all their data.

So if the only time you save your state is in your app’s OnSuspending method, you’re asking for trouble. If a user closes your app, and then re-launches it again less than ten seconds later, they will lose all the data they entered during their previous session, and maybe everything.

Now, why would somebody do that — close the app and then re-launch it right away? Beats me. Maybe they close it and then think of something else they wanted to do. Maybe your app doesn’t have a Home button and they’re frustrated with trying to find their way back. Maybe the app doesn’t correctly refresh the date when you resume it the next day (Microsoft’s XBox games, with their date-sensitive daily challenges, are really bad at this).

But you know what? It doesn’t matter why they do it. Closing and reopening is a totally innocuous action. It should not screw the user out of their data.

Right now, I don’t have a great alternative to recommend; I just ran into the problem, I haven’t solved it yet. I’ll probably keep the “save on suspend”, so I have a chance to save the latest and greatest state; but I’ll probably also add some background saves as well. But of course all those saves will be async operations, so I have to come up with a way to make sure they don’t step on each other. Good times.

Stop writing INotifyPropertyChanged, start using UpdateControls

December 16th, 2012

If you use MVVM, you know all about INotifyPropertyChanged, and mostly you know that it’s a pain. Simple properties are a lot of code, but otherwise not too bad; but once you start having derived properties, it’s hard to make sure you fire all the right change events at the right time (and even harder to keep it right as you refactor).

Can’t we do things the way Knockout.JS does, with a framework that automatically discovers the dependencies for you?

Why yes, yes we can. Last weekend I discovered UpdateControls.

Introduction to UpdateControls

UpdateControls is free and open-source (MIT license), is available via NuGet, and works pretty much everywhere: WinRT, WPF, Silverlight, Windows Phone 7 — even WinForms! Update: WP8 is supported too.

The idea is:

  • Don’t implement INotifyPropertyChanged on your viewmodel.
  • Wrap each of your independent variables inside an Independent<T> instance. Expose the underlying value through properties.
  • For computed properties, just write the code to compute the values.
  • Before you assign your top-level viewmodel to a DataContext, wrap it with a call to ForView.Wrap.

And that’s it. You don’t need to fire notifications manually; UpdateControls does it for you.

An example:

public class MyViewModel {
    private Independent<string> _firstName = new Independent<string>("");
    private Independent<string> _lastName = new Independent<string>("");
    private Independent<bool> _lastNameFirst = new Independent<bool>();

    // Expose independent values through simple wrapper properties:
    public string FirstName {
        get { return _firstName; }
        set { _firstName.Value = value; }
    }
    public string LastName {
        get { return _lastName; }
        set { _lastName.Value = value; }
    }
    public bool LastNameFirst {
        get { return _lastNameFirst; }
        set { _lastNameFirst.Value = value; }
    }

    // Dependent (computed) properties are just code:
    public string Name {
        get {
            if (LastNameFirst)
                return string.Format("{0}, {1}", LastName, FirstName);
            else
                return string.Format("{0} {1}", FirstName, LastName);
        }
    }
}

// And in the view:
DataContext = ForView.Wrap(new MyViewModel());

And like magic, all your properties, all your logic, will start notifying the UI of changes. Between the ForView.Wrap wrapper at the top and the Independent<T> at the bottom, UpdateControls is able to automatically track all the dependencies, and triggers change events for computed properties whenever their ingredients change. This even works if a property changes which ingredients it uses.

ForView.Wrap wraps your top-level viewmodel in an internal class called DependentObject<T>. The first time a databinding asks for a property, the DependentObject<T> switches into recording mode, and then invokes your viewmodel property. Until that property returns, the DependentObject<T> takes note of every time you read the value from any Independent<T> anywhere; and whenever you do, it hooks that Independent<T>‘s change event.

Then the DependentObject<T> caches the property value and returns. Next time XAML asks for the value, it just returns it. (Its ingredients haven’t changed, so why not?) But as soon as any of the ingredients change, it clears its cache and fires PropertyChanged. There’s a lot of magic under the covers, but using it is dead simple. In principle.

As with any magic, there are some subtleties and gotchas, which I go into below. But first, some important notes about the documentation.

API drift, or, an UpdateControls documentation survival guide

UpdateControls has a fair bit of documentation, including several good videos. Unfortunately, the API has changed in a couple of significant ways over time, but a lot of documentation still refers to the old APIs. So some places you see it one way, and some places you see it the other way, which is hella confusing.

The old APIs do still work (though not on every platform and not with every edition of Visual Studio), but there are easier — and more universal — ways to do things now.

Here are the two things you really need to know before you start reading the UpdateControls documentation:

Codegen vs. Independent<T>

Independent properties used to take more code than what I showed above. It was so tedious that the author even wrote a Visual Studio add-in to do the code generation for you. But now we have Independent<T>, which is enough simpler that you don’t need codegen. The old way still works (as long as you don’t have Visual Studio Express, which doesn’t support add-ins), but Independent<T> does a better job of encapsulating the boilerplate code, so IMO it’s the way to go.

Unfortunately, most of the code samples and screencasts still use the old way. You’ll see (and hear, in the videos) lots of references to Ctrl+D G, which tells the VS add-in to do its code generation. And you’ll see a lot of code like this:

private string _firstName;

#region Independent properties
// Generated by Update Controls --------------------------------
private Independent _indFirstName = new Independent();

public string FirstName
{
    get { _indFirstName.OnGet(); return _firstName; }
    set { _indFirstName.OnSet(); _firstName = value; }
}
// End generated code --------------------------------
#endregion

My advice: Don’t install the MSI (in these days of NuGet, the MSI is really just there to install the VS add-in). Ignore the VS add-in entirely. Tune out whenever the videos talk about Ctrl+D G.

Just add the NuGet package to your project, and then use Independent<T>. The above code becomes this, which is simple enough to write and maintain by hand:

private Independent<string> _firstName;

public string FirstName {
    get { return _firstName; }
    set { _firstName.Value = value; }
}

By the way, that’s not a typo in the getter. You can return _firstName.Value if you like, but Independent<T> also has an implicit conversion to T, so as long as it’s not Independent<object> you can indeed just return _firstName;.

{u:Update} vs. plain old bindings

Originally, UpdateControls had a XAML markup extension ({u:Update}) that you were supposed to use in place of {Binding}. It took care of turning on dependency-recording mode whenever values were bound to the UI, so that it knew how to watch for changes and update the UI when ingredients change later.

Unfortunately, not all the XAML platforms support markup extensions. Silverlight didn’t get them until v5. Windows Phone 7 doesn’t have them; not sure about 8. WinRT doesn’t support them. {u:Update} isn’t going to cut it for those platforms. I suspect that {u:Update} also wouldn’t play well with visual designers like Blend; they’re all about the {Binding}.

So UpdateControls added ForView.Wrap(), which you can use in combination with plain old {Binding}. If the objects you expose to your XAML and your DataContexts and your Bindings are wrapped for view, you get the same magic, but without needing markup extensions.

Any time you see {u:Update} in the documentation, just mentally substitute {Binding}, and make sure the viewmodel gets wrapped with ForView.Wrap before the view sees it. For example:

// Using the PersonViewModel class from the first code sample, above:
var viewModel = new PersonViewModel();
view.DataContext = ForView.Wrap(viewModel);

<!-- This will automatically update whenever ingredients (FirstName, LastName) change. -->
<TextBlock Text="{Binding Name}"/>

Gotchas

If you’re starting with UpdateControls on a new project, I would imagine it’s not too hard to follow the rules and have things work well. If you’re integrating it into an existing code base, you’re more likely to run into gotchas. Here are some of the problems I ran into when trying to refactor my project to use UpdateControls.

Don’t use INotifyPropertyChanged

If your viewmodel implements INotifyPropertyChanged, UpdateControls assumes you know what you’re doing, and ForView.Wrap won’t wrap that class; instead it presents your class as-is to the view. The consequence is that the computed-property notification magic won’t work for your INPC class or anything inside it. If you implement INotifyPropertyChanged, it’s all on you.

Which means that, if you’re trying to refactor from INPC to UpdateControls, you can’t do it one property at a time. To use Independent<T>, you can’t have INotifyPropertyChanged. You’ll have to change your entire viewmodel class at once: remove INotifyPropertyChanged, add Independent<T>s for everything, all in one fell swoop.

If you do viewmodel composition — where one viewmodel exposes other viewmodels as properties (think nested panels inside a larger screen) — then you probably want to start at the top level (the whole screen), and work toward the leaves (nested panels).

Corollary: Don’t use ObservableCollection<T>

I had viewmodels that exposed collections, and nothing was happening when the collection items’ properties changed. It turns out that ObservableCollection<T> implements INotifyPropertyChanged (makes sense when you think about it; you might want to bind to its Count) — so UpdateControls just exposed the collection instance directly to the UI, without attaching any of the dependency-recording logic: not for the collection itself, and not for the items inside it, either.

So don’t use ObservableCollection<T> with UpdateControls. Use IndependentList<T> instead (it’s the UpdateControls equivalent of an observable collection). Or just a plain old List<T> if the contents aren’t going to change. Or even a LINQ query (great for filtering — as long as the filter conditions boil down to Independent<T>, changing them will automatically re-run the LINQ query). But if you start using UpdateControls, you should get rid of all your references to ObservableCollection<T>.

ForView.Wrap and dependency properties

This one may be peculiar to my code, but I had some custom dependency properties whose value was a custom class. Once I started using UpdateControls, their value wasn’t that custom class anymore; the view layer (where dependency properties live) operates on the wrapper objects, not the actual viewmodels. Since my DependencyProperty.Register call specified that the property value should be of type MyCustomClass, but the actual instance was a DependentObject<MyCustomClass>, the bindings saw a type mismatch and never set my property. To get around this, I had to change my DependencyProperty.Register call to specify object as the property’s value type. (And of course my property’s change event had to use ForView.Unwrap<T> instead of casting directly to the class type.) This probably won’t affect many people, but it’s worth noting since I burned some time trying to figure it out.

Debugging wrapper objects

If you’re in the debugger, and you’re looking at a wrapper object (from ForView.Wrap), the tooltip will show the ToString() from the wrapped class — which is often the name of the wrapped class. It can be hard to even realize that the object you’re looking at is a wrapper, and not the viewmodel itself.

It’s not hard if you know how, though. If you expand the tooltip, wrappers will have a “HasErrors” property, and not much else. That should be easy to tell apart from your actual viewmodel (which will typically have lots of properties).

If you then want to drill down to see the properties of the wrapped instance, you can expand “Non-Public Members”, then “_wrappedObject”.

Debugger tooltip with UpdateControls

Integrating with Caliburn.Micro

I tried combining both UpdateControls and Caliburn.Micro in the same project, mostly because I was already using Caliburn.Micro’s IViewAware so my viewmodels could fire animations on the view and wait for them to complete. Here’s what I learned:

  • Don’t use Caliburn.Micro’s base viewmodel classes, because they implement INotifyPropertyChanged (see above).
  • Caliburn.Micro doesn’t know about UpdateControls’ wrapper classes. If you’re doing viewmodel-first (where Caliburn.Micro automatically discovers and instantiates the correct view type for you), and your DataContext is a DependentObject<PersonViewModel>, Caliburn.Micro’s conventions will probably look for a DependentObjectView or something — it doesn’t know that it’s supposed to look for a PersonView. This isn’t hard to deal with, though; Caliburn.Micro has good extensibility points for this sort of thing.
  • The IViewAware stuff won’t work out of the box either, because Caliburn.Micro takes the DataContext and says “does it implement IViewAware?” and of course it doesn’t, because it’s got the wrapper object, not your viewmodel. None of the lifecycle stuff (IGuardClose and the like) would work either, because it’s also based on interfaces. Again, you could hook CM’s extensibility points to make this work.
  • No idea how Caliburn.Micro’s {x:Name}-based binding conventions would play with UpdateControls. I didn’t get that far.

In the end, I decided not to use Caliburn.Micro for this app. I had a lot of custom UI, so the conventions weren’t much use to me; I was really only using CM for IViewAware, which would require some coding to integrate with UpdateControls. Easier to roll my own at that point.

But I’m confident you could use the two together. If anyone digs into this further and wants to share their code, drop me a line and I’ll either post it or link to you.

Conclusion

I’m pretty excited about UpdateControls. Yeah, I spent a lot of time here talking about the downsides and gotchas. But I wouldn’t have bothered if it didn’t show so much promise.

If you’ve used Knockout, or if you’re tired of keeping track of which calculated properties to fire PropertyChanged events for whenever something changes, you owe it to yourself to take a look at UpdateControls.

Here’s where to start:

  • First, look through the notes above about API drift. You’ll want to be able to mentally translate the out-of-date code samples as you see them.
  • Then head over to the UpdateControls documentation and read through all half-dozen or so pages; they’re short. Also take a quick look through the other sections in the sidebar (“Examples”, “Tips”, “Advanced Topics”).
  • Then check out the videos, which cover different material than the docs, and which dig a lot deeper. They’ll really give you an idea of what UpdateControls can do.

My current project: Stupid Quest

December 12th, 2012

I haven’t blogged much in a while, and I need to. I’ve been writing a video game (aren’t I always?), and there’s stuff to blog about.

But for now, I’ll just post an early screenshot. (The real thing will run fullscreen, as a Windows 8 app.)

Screenshot of the Stupid Quest battle screen

Attacking isn’t working yet, so the monsters just taunt you.

Hmm. It looks a lot better with animation. Oh well.

User group presentation on AvalonEdit

December 12th, 2012

This month, the Omaha .NET user group did lightning rounds. I did a presentation on AvalonEdit.

If anyone’s interested, here’s the video: 2012 December Omaha .NET User’s Group. My part goes from 1:02 to 1:20. The slides are pretty readable in the video, the code less so. The audio isn’t great, but is mostly intelligible. If anyone’s interested, check it out.

I haven’t made my code available for download, but I keep intending to. If anyone’s interested in the code, drop me a note.

Also presenting were:

  • Volker Schulz, “Windows Azure – Build, Debug and Deploy” (0:00 to ~0:35)
  • Naveen Akode, “MSBuild – Basics and Usage” (~0:35 to ~1:02)
  • Brian Olson, “WebAPI and Moustache” (~1:20 to ~1:35)

XamlParseException in WinRT

September 6th, 2012

I’m writing a video game (as always), this time as a Windows 8 app. Currently I’m still developing on a VM running the Release Preview of Windows 8 and Visual Studio 2012, but I just got a chance to build and run on a machine running the final RTM versions of both.

When I ran my app, it showed the splash screen for a second or so, then dumped me back to the Start screen. So I tried running under the debugger, and got a XamlParseException: “XAML parsing failed.”

<rant>

I’ve commented before that Microsoft obviously put their most junior programmers to work on writing the WinForms ToolStrip in .NET 2.0. (If you haven’t had to deal with the flaky design, and bugs, of ToolStrip, be glad.) They had to give ToolStrip to their junior devs, because all their experienced devs were already busy working on WPF.

With WinRT, it’s pretty clear that all their junior people were working on error handling. The number of things that fail with absolutely meaningless errors (e.g. “A COM error occurred”) is staggering. Makes me wonder what they’ve got the senior devs busy on, if it’s not WinRT.

</rant>

Anyway, it turns out the problem is a codegen bug if your assembly has a dot in its name. There’s a simple workaround: go into Project Properties > Application tab > Assembly name, and change it to something with no dots in it. (I’ll probably also rename the .csproj and the folder to match, but that’s not necessary.)

The knowledgebase article says this is a problem with XAML-based controls, but I haven’t seen a problem with our WPF4 code at work. So either it’s only WinRT (rather than all XAML as the KB article suggests), or it’s only a problem with .NET 4.5.

There’s allegedly a hotfix that will fix the codegen bug properly, but there’s no actual way to download the hotfix. Easiest thing is to rename the assemblies, or wait for the service pack.

System colors in WinRT/XAML

July 20th, 2012

Windows apps have always adapted to the Windows color settings. But over time, Microsoft has made this progressively harder.

In WinForms, you had SystemColors and SystemBrushes, which were well-documented and easy to use. In WPF, you had a new flavor of SystemColors, which were fairly well-documented, but using them required a lengthy incantation involving DynamicResource. In HTML Metro (WinJS), you can expand out the references in Solution Explorer and read the theme CSS files, which is less discoverable than anything before, but is still a little like documentation.

But in XAML Metro (WinRT/XAML), the system colors are buried in theme resources that you can’t even see. If you want to use one of the system colors, you can find them in the visual designer’s Properties page, but you can’t find them in the documentation. This bugs me, since I’m a coder and tend not to bother much with the designer.

So I went ahead and wrote the documentation myself. I now have a metro.excastle.com subdomain, which contains documentation for the system brush resources in WinRT/XAML. I even show color swatches for both the Dark and Light themes. (I recommend you use a modern browser that understands CSS alpha transparency.)

(BTW, if anyone can suggest a better algorithm for deciding whether a semi-transparent color’s RGB code should be shown in black or white for best contrast, I’m all ears. I admit I didn’t spend a lot of time on that part.)

If you have suggestions for other content or links I could add to metro.excastle.com, leave a comment here or drop me a line.

Running Windows 8 Release Preview in a virtual machine

July 1st, 2012

I just spent the whole weekend trying to get the Windows 8 Release Preview and Visual Studio 2012 Release Preview running in a VM on my personal laptop. I think I may have it working now, though I’ve been burned by enough false starts that I’m not willing to call it yet. But I’ve certainly learned enough to be worth sharing.

If you’re more interested in the destination than the journey, skip ahead to the tl;dr.

Reasons for a VM

I didn’t want to install Windows 8 as the primary OS on my laptop, for two main reasons:

  • I’m not impressed with its stability. The week I was at TechEd with the company laptop, the video driver crashed an average of twice a day. Sometimes it recovered, but sometimes (usually when waking from sleep) the machine bluescreened. (Granted, that’s just the video driver; but the Windows 7 video driver never had any problems.)
  • My laptop came with some software called Beats Audio that seriously improves the sound quality. Because it was shovelware, I don’t have a separate installer for it, so I would have no way to install it on Windows 8, and watching Netflix would suck a lot without the good audio.

The second reason was really the biggie. What can I say? I bought this laptop for audio first, development second.

So my choices were between a VM and dual-boot. And a VM would make it a whole lot easier to switch back to Windows 7 to watch Netflix, so I was leaning strongly toward a VM if I could make it work.

Requirement: Run fullscreen

My laptop’s screen is 1366×768. Windows 8 disables some features, like Snap, if your screen is any smaller than 1366×768. Since I want to develop Metro apps, and test them with things like snapped mode, I have to be able to run my VM fullscreen. I assumed this wouldn’t be a big deal.

What a fool I was…

First failure: VirtualBox

I started with a c|net article called Install Windows 8 virtually with free software. It covered both VirtualBox and VMWare Player. I’ve used VMWare before (Workstation though, not Player), so I figured I’d try something new, and try VirtualBox first.

The version of VirtualBox I tested is 4.1.18. The UI is pretty clean and usable. I created the virtual machine, installed Windows 8, installed the Guest Additions, switched to fullscreen mode, and…

…it didn’t go fullscreen.

My laptop’s screen is 1366×768. VirtualBox, in fullscreen mode, only ran the guest at 1360x768. So there was a three-pixel black bar at the left and right sides of the screen.

I tried using Snap just on the off-chance that Microsoft had left a few pixels leeway on that 1366×768 requirement. They had not.

Six pixels. So close, and yet so far.

I did some research, and found that VirtualBox used to have a bug where it would round the width down to the nearest multiple of 8. (Which doesn’t make the slightest bit of sense. It’s not like it’s a memory-alignment issue; each individual pixel is already 32 bits, so everything is already 32-bit aligned.)

But they claimed to have fixed this bug 19 months ago. So either they broke it again, or they lied about having fixed it.

I found a StackExchange question from someone else with the same problem, and they claimed to have fixed it by going into the VirtualBox settings and bumping up the guest’s video memory to 128MB. But my guest was already set to 128MB of video memory; that had been the default. I tried increasing it to 256MB, but no good: the screen was still that fatal 6 pixels too narrow.

It was about this time that I decided to post a question on SuperUser and then try plan B. Alas, the question didn’t get an answer until I knew enough to go back and answer it myself. But that’s later.

Second failure: VMWare Player

I soon lost count of how many hoops I had to jump through just to download VMWare Player. I had to register, but I couldn’t register because they already had a registration under my e-mail address, but they wouldn’t accept my best guess at a password, so I had to do the “Forgot Password” and reset my password. Then I went back to the download page, and they prompted me to log in again. (Earth to VMWare: I just entered my new password when I reset it!) So I logged in again, and then they forgot what it was I had wanted to download. I used Google to find the download page again, and then they’d let me select the software to download, but they asked me to accept the license agreement first, and when I did, they promptly forgot what I was downloading again.

Downloading VMWare Player was almost as maddening as it had been trying to get VirtualBox to work.

But I finally did manage to get it downloaded. The version of VMWare Player I used is 4.0.4. I can’t say I care for the puffy blue window, but it seemed functional enough. Followed the instructions to get Windows 8 installed (apparently VMWare is pretty touchy about Windows 8 unless you perform all the right song and dance), and got it up and running. Great!

I installed the VMWare Tools in the guest, installed the Visual Studio 2012 release preview, created a new Metro grid application, ran it, and…

…FAIL. The app started up fine, the first screen animated in — and the instant the animation stopped, all the images disappeared.

The “Grid application” project template comes with some sample images that it displays on the grid tiles. They’re all various shades of solid gray, but they’re still images. And apparently the video driver in VMWare Tools has a problem with the way Metro apps display images. So as soon as the screen is done animating in, all the tiles vanish, and all that’s left is the text.

Older versions of Windows had someplace in Display Options where you could ratchet down the video acceleration if things weren’t displaying properly, but either Windows 8 doesn’t have those options anymore, or they were disabled for the virtual video driver inside VMWare. I looked inside the VMWare Tools options, but there was nothing about graphics acceleration. And unlike VirtualBox, VMWare doesn’t seem to have video acceleration options in the host app. Nowhere could I find even a single knob to try to fix this problem.

And there’s no way in hell I can develop a Metro app in a VM that can’t show half the app’s UI.

I spent a while longer trying to make this work. I tried a refresh of Windows, in case it was some Windows setting that had gotten out of whack. Then reinstalled VS2012, re-created my project, re-ran it. And the images re-disappeared.

There’s not even anywhere to go from here. Dead-end on VMWare Player.

Third failure: Forcing Snap

During the course of my research, I had run across some articles that said there was a Registry setting that would force Windows 8 to always enable Snap, even if the screen resolution was too low.

I figured I could give that a go; as long as I planned carefully, the six-pixel error might not throw off my testing too much. So I went into my six-pixels-too-small VirtualBox VM, created the Registry setting, and tried snapping some apps. But the “snap” gutter never appeared: it just wanted to task switch, not snap.

Well, maybe I need to restart Windows in the VM before the setting will take effect. Tried it. Still no good.

It looks like the “force Snap” Registry hack no longer works in the Release Preview.

Eventual, roundabout, partial success: Remoting into VirtualBox

VirtualBox has a feature where it can run an RDP server, so you can remote into your virtual machine. So I figured, hey, maybe I can minimize the VirtualBox window and Remote Desktop into the VM. Remote Desktop doesn’t have any stupid multiple-of-8 restrictions, so it might work.

So I went into VirtualBox and enabled “Remote Display” (their name for their RDP server), and then tried to connect to it.

Here’s a little tip for UI designers: if a particular feature will only work if the user has installed an add-on product, then don’t show the UI options for configuring that feature unless the user has actually downloaded and installed the necessary add-on. I burned quite a bit of time trying to figure out why all my settings were accomplishing nothing. Turns out you have to download and install the VirtualBox Extension Pack before VirtualBox will actually support all the RDP options you’ve spent the last hour fruitlessly trying to configure.

If you want to try to use VirtualBox’s RDP support, don’t expect it to work in any kind of reasonable way; just save yourself time and read the manual. I finally got it set it up, and managed to get the headless server started from the command line.

And Remote Desktop connected! And gave me a black screen.

So I minimized Remote Desktop and looked in the server’s console window, to see if it had reported any errors. It had not, but now I noticed a mysterious new window on my host machine, and it looked like it was showing the VM screen that was supposed to be getting sent over Remote Desktop. This mystery window’s title bar said “Chromium Render SPU”, so off to Google I went.

Turns out the problem here is VirtualBox’s 3D acceleration. If you have 3D acceleration enabled, then the host renders to the mystery window instead of to RDP. Very screwed up. But the message-board thread said all you have to do is disable 3D acceleration, and Remote Desktop will start working.

So I shut down my VM (trying to click in about the right place in Remote Desktop to hit the “power” icon, then minimizing everything so I could look at the mystery window and see if I’d clicked in the right place; rinse, repeat), then went into my VM’s settings and turned off 3D acceleration, connected Remote Desktop again, and ha, I got a login screen!

I maximized the Remote Desktop window, and it went fullscreen, but the remote desktop was only 1024×768, centered on my 1366×768 screen. So I went into “Screen resolution” on the remote machine, and lo and behold, for the first time in VirtualBox, 1366×768 was an option in the list! I selected it, and…

(angelic choir)

…it worked. My VM was running fullscreen at 1366×768.

Then, on some crazy whim, I shut down the VM, opened it the normal way through VirtualBox Manager, and it was still 1366×768. Something I had done while trying to enable Remote Desktop had actually fixed the original problem!

Coming down from the euphoria, and a conclusion

So somehow, in this long crazy string of events, I had done something that had finally kicked VirtualBox over the hump and into proper fullscreen support. I was a little nervous about touching anything at this point, lest it revert to its original broken state. But at the same time, I like to clean up after myself. I don’t really want an unauthenticated RDP server running on my laptop anytime I’m running Windows 8.

So I started backing out my changes. I turned off the RDP server. And as long as I’m running locally, I might as well turn 3D acceleration back on. Restart the VM…

Black bars.

1360×768.

And at this point I had an inkling of a suspicion. (And it was this suspicion alone that kept me from descending into madness.) I shut down the VM, turned 3D acceleration back off, and started the VM.

Worked like a charm. Fullscreen goodness.

What a letdown. I had burned an entire freaking weekend on what boiled down to a single buggy setting.

(What’s worse, I can’t even report the bug without giving Oracle three forms of ID and a note from my mother. Who the hell made the Marketing department the gatekeepers for the bug tracker?)

Anyway, the VM seems to be working so far. No blank screens, no mystery windows. It actually does run fullscreen, no black bars, the full 1366×768. I can snap apps like a champ. I installed VS2012 in the VM, created a new grid app, and ran it, and not a single image disappeared. It all seems fine, though of course only time will tell.

One freaking setting.

tl;dr

To run Windows 8 in a VM: Don’t bother with VMWare Player. Use VirtualBox and disable its 3D acceleration.


Joe White's Blog copyright © 2004-2011. Portions of the site layout use Yahoo! YUI Reset, Fonts, and Grids.
Proudly powered by WordPress. Entries (RSS) and Comments (RSS). Privacy policy