Archive

Archive for March, 2013

Eventless Programming – Part 5: Async/Await and Throttling

March 3, 2013 2 comments

Posts in this series:

Last time we were able to throw a few more working features into our UI with relatively little effort, following very simple patterns. The result is that the UI automatically updates itself according to every change the user makes to the state of a control.

Which raises the question: what if that involves working a little too hard? If the user makes half a dozen changes in quick succession (say, they impatiently click the “Increase Radiation” button five times) then it makes little sense to do a ton of work to update the UI after every single click. It would be wiser to wait until they stop clicking it for half a second or something.

This is especially important when the updating work involves something really costly like downloading content over the network. And that’s another point – how do we integrate with asynchronous background calls? Oh no, my whole universe is starting to crumble!

Except it’s not. There are simple answers to both questions. Let’s start with the rapid-fire-recomputations problem. Recall that in our Notes view model, we cook up this:

SelectedNotes = Computed.From(
    () => AllNotes.Where(n => n.IsSelected.Value).ToList());

This means that every time you check or uncheck the selection CheckBox for a note, a Where/ToList is re-executed, and then various bits of UI infrastructure get rejigged as a result of SelectedNotes changing. In fact we can easily monitor how often this happens by adding this line:

Computed.Do(() => Debug.WriteLine("SelectedNotes: " + SelectedNotes.Value.Count()));

Now try clicking Select all and you’ll see the crazy results:

SelectedNotes: 0
SelectedNotes: 1
SelectedNotes: 2
SelectedNotes: 3
SelectedNotes: 4
SelectedNotes: 5
SelectedNotes: 6
SelectedNotes: 7
SelectedNotes: 8
SelectedNotes: 9
SelectedNotes: 10
SelectedNotes: 11
SelectedNotes: 12
SelectedNotes: 13
SelectedNotes: 14
SelectedNotes: 15
SelectedNotes: 16

Yes, as we loop through the notes setting IsSelected to true, every single time the SelectedNotes list is recomputed and so triggers UI updates. It may not be a problem in this little example, but it’s not to hard to see how it could become a problem if the UI update were more expensive.

So that’s why it needs to be this easy to fix it:

SelectedNotes = Computed.From(
    () => AllNotes.Where(n => n.IsSelected.Value).ToList()
).Throttle(100);

Yep, you just tack .Throttle(100) on the end, and it configures the Computed to wait until it hasn’t been notified of a change in its dependencies for at 100 milliseconds before acting on it; that is, it waits for stability. There’s actually a second parameter bool that lets you select between two behaviours:

1. true: wait for n milliseconds of stability (the default)
2. false: recompute no more than once every n milliseconds during instability

The default behaviour means that if the user keeps making changes back and forth indefinitely, the UI will never update. But of course in reality they don’t do that, so it’s usually fine. But if you wanted to show continuous feedback while (say) the user drags a slider, maybe the second behaviour would be more suitable. There’s no hard and fast rule here, which is why it’s an option.

Now let’s do some asynchronous downloading. Say we have a TextBox where the user types a URL, and we are going to download it automatically as they type. In reality they’d be adjusting a more restricted set of parameters than just a raw URL, of course, but it serves as an example. First we’d bind the TextBox to a Setable.

var urlText = Setable.From(string.Empty);
textBoxUrl.BindText(urlText);

Then from that we’d compute a Uri object, or null if the string isn’t yet a valid URI.

var uri = Computed.From(() =>
{
    Uri result;
    Uri.TryCreate(urlText.Value, UriKind.Absolute, out result);
    return result;
});

So far, so obvious. But it turns out the last part isn’t too surprising either:

var response = Computed.From(async () =>
{
    if (uri.Value == null)
        return "You haven't entered a valid url yet...";

    try
    {
        return await new HttpClient().GetStringAsync(uri.Value);
    }
    catch (HttpRequestException x)
    {
        return "Error: " + x.Message;
    }
}).Throttle(1000);

You just put the async keyword in front of the lambda you pass into Computed.From (and of course you should probably use Throttle, as I’ve done here). So what is response? It’s an IGetable, as you’d expect, but what type of Value does it hold? By inspecting the various return statements of our lambda, it’s pretty clear that it returns a string, but it is an async lambda so therefore it returns Task<string>.

But Computed.From has a special overload for Task<T> that takes care of await-ing the result value. So the upshot is that response is simply a IGetable<string> and can immediately be bound to a control:

textBoxResponse.BindText(response);

When used inside a UI application, async/await automatically ensures that if you launch a task from the UI thread and await it, the await will return on that same UI thread. So your UI code never has to worry about threads much at all, which is very reassuring (it’s not like the old days, when you had to manually use Control.Invoke to ensure that your UI updating operations happened on the right thread).

The complete source code for this series of articles is available here:

https://github.com/danielearwicker/eventless

It’s a Visual Studio 2012 solution.

Next time… well, actually I’m going to pause here for a while. The next step would be to see how we can apply these ideas to a more current UI framework like Windows Runtime. In the meantime, I hope it’s been interesting to see how the core ideas of Knockout are applicable in environments that have nothing to do with HTML and JavaScript, and it’s not actually about binding to the UI. The key thing is providing a highly productive way to transform your raw data. That’s what makes the binding part easy. So unless you make the data transformation easy, then you’ve just moved the problem without solving it. Computed observables are what make it possible to declare your data transformations, and so enable eventless programming. They are the secret sauce of Knockout.

Advertisements
Categories: Uncategorized Tags: , ,

Eventless Programming – Part 4: More Views Than You Can Shake A Stick At

March 2, 2013 Leave a comment

Posts in this series:

Last time we got a basic UI together. Next we’ll throw lots of typical ingredients into it, but common theme will be: everything stays consistent. And there ain’t much code.

First of all, just to follow a tidy pattern, we’ll define a proper “view model” class for our main Form:

public class Notes
{
    public readonly ISetableList<Note> AllNotes = new SetableList<Note>();
    public readonly IGetable<IEnumerable<Note>> SelectedNotes;
    public readonly ISetable<Note> ActiveNote = new Setable<Note>();

    public Notes(IEnumerable<string> initialNotes)
    {
        AllNotes.AddRange(initialNotes.Select(
            text => new Note(this) { Text = { Value = text } }));

        SelectedNotes = Computed.From(
            () => AllNotes.Where(n => n.IsSelected.Value).ToList());
    }

    public void Add(string note)
    {
        AllNotes.Add(new Note(this) { Text = { Value = note } });
    }
}

This is just the same code as before, minus any bindings to UI controls. The idea is that you could then make a bunch of different views that bind to the same data (and of course, you can write unit tests). We won’t bother to do that with the whole Notes system, but we will do it for individual notes. I just wanted to neaten this up before continuing.

There is one new thing: the ActiveNote property. Nothing fancy, it just holds a single Note (or null, of course).

I’ve changed Note so it takes a reference to Notes in its constructor (oh yes, it has a constructor now):

public class Note
{
    public readonly ISetable<string> Text = new Setable<string>();
    public readonly ISetable<bool> IsSelected = new Setable<bool>();
    public readonly ISetable<NotePriority> Priority = new Setable<NotePriority>();
    public readonly ISetable<bool> IsActive;
        
    public Note(Notes notes)
    {
        IsActive = Computed.From(
            get: () => notes.ActiveNote.Value == this,
            set: value =>
                {
                    if (value)
                        notes.ActiveNote.Value = this;
                    else if (notes.ActiveNote.Value == this)
                        notes.ActiveNote.Value = null;
                }
        );
    }
}

This allows it to set up its own new IsActive property that is true only if this property is currently the active one. It’s Computed with a getter and a setter, so it provides a different way to interact with Notes.ActiveNote:

noteA.IsActive = true; // activeNote is now noteA
noteB.IsActive = true; // activeNote is now noteB
noteB.IsActive = false; // activeNote is now null

So although it looks like each Note has an independent bool property, they are utterly co-dependent. Only one can be true at a time. Compare this to the typical hacky approach where you actually give each Note a separate bool and then try to keep them in line by manually setting them. How much more elegant to just declare how to simulate a bool property by using a single shared ActiveNote property. It’s pure poetry!

The main NotesForm just sets up the binding to UI controls. In fact I’ve made it implement IBindsTo<Notes> just to follow the pattern. But really this is the same code as before, just rearranged. Oh, I added the concept of NotePriority:

public enum NotePriority
{
    Normal, Low, High
}

So Note has an setable Priority as well. So we have a couple of new things we could bind to in NoteListItemForm:

public void Bind(Note note)
{
    textBoxContent.BindText(note.Text);
    checkBoxIsSelected.BindChecked(note.IsSelected);

    Computed.Do(() => BackColor = note.IsActive.Value
                            ? SystemColors.Highlight
                            : SystemColors.Window);

    Computed.Do(() => pictureBox.Image = 
        note.Priority.Value == NotePriority.High ? Properties.Resources.high :
        note.Priority.Value == NotePriority.Low ? Properties.Resources.low :
        null);

    textBoxContent.Click += (s, ev) => note.IsActive.Value = true;
}

This is a chance to show how you can bind anything in your UI, even if there isn’t a special extension method for whatever it may be. The trick is to use Computed.Do, which we haven’t used so far. It’s just like Computed.From but it returns void and takes a plain Action. Now what the heck is the point of that? A computed observable that computes nothing and gives you back nothing to observe? Oh but it does! As with any void function, it returns a new version of the universe. Or more mundanely, it has side effects on this universe. Or even more mundanely, it has side-effects on some control in our UI.

The beauty of it is that it runs the action once when you set it up, and then again whenever anything it depends on changes. So although you have to write imperative side-effecting statements, they are typically just assignments, and the right-hand side is an expression in terms of observables, just like you’d use in a binding. So it’s a way to roll your own kind of binding. Here I have two examples: the background color is different for the active note, and an icon is used for the two non-normal priorities:

part4-active-icons

There’s also a plain old Click event handler so the user has a way to set this Note to be the active one.

We can also display a more expanded view of the active note, using another small form called NoteEditingForm, which implements IBindsTo<Note> in the usual way.

part4-active

Edit the text in the active view and it immediately changes in the list, and vice versa. Cool!

This is ridiculously easy. On the main form we add a new empty Panel, and then we bind it like this:

panelActiveNote.BindContent(notes.ActiveNote).As<NoteEditingForm>();

That’s it. BindContent is actually a close relative of BindForEach, the difference being that it uses a single value that may be null, which we could think of as a list that has either zero items or one item. NoteEditingForm has one minor thing we haven’t seen previously: binding to radio buttons:

public void Bind(Note note)
{
    textBoxContent.BindText(note.Text);
    checkBoxIsSelected.BindChecked(note.IsSelected);

    radioButtonHigh.BindChecked(note.Priority, NotePriority.High);
    radioButtonNormal.BindChecked(note.Priority, NotePriority.Normal);
    radioButtonLow.BindChecked(note.Priority, NotePriority.Low);
}

Easy-peasy. Okay, so what else could we do? What if there was an alternative view where we just show you a big scrollable list of these NoteEditingForm tiles? Sounds like a lot more work… No, you dummy! It’s just this:

panelEditors.BindForEach(notes.AllNotes).As<NoteEditingForm>();

And immediately we have this:

part4-editors

Of course, you can edit in one view and it changes in all the others. They’re all bound to the same simple underlying view model, and the bindings are declarative, and therefore hard to get wrong. It makes the UI very malleable – you can very quickly try out ideas, move pieces around, and know that the pieces will keep working. And that in turn gives you the power to make a better UI, because experimentation (with feedback from real users, even if that’s just yourself) is the only way to make a better UI.

Code in the usual place. Next time, how we can integrate with async/await, and use throttling to reduce the rate of recomputation.

Categories: Uncategorized Tags: , ,

Eventless Programming – Part 3: Binding to a UI

March 2, 2013 Leave a comment

Posts in this series (and if you’ve been following so far, have another quick read-through – there’s been some renaming again…):

Last time we figured out how to create a second kind of observable, one that defines its value using a function. The burning question is: how are we going to tie these things to a UI?

Consider knockout, the inspiration for this whole exercise. There, the UI is defined by HTML. Special data-bind attributes are added to easily link observables up to various properties.

Now, in the C# Windows GUI world there has been some turmoil over the last year or so (to put it mildly). Do we go with WPF, Silverlight or Windows Runtime? Wait a second, we’re forgetting poor old reliable, sleepy, uncontroversial, it-just-works Windows Forms! For fun, let’s start by rewriting the past. How should we have been making Windows apps in 2003?

Aside from anything else, Windows Forms has a very easy to use GUI design tool for us to layout controls on. But there’s no “mark-up” for us to extend with custom attributes. Aw, don’t cry! We’re not going to give up just yet. We can just provide a way to set up bindings from code and it’s all going to be fine.

var newNoteText = Setable.From(string.Empty);

textBoxNewNote.BindText(newNoteText);

// 'Add' button is only enabled if text box is non-empty
buttonAdd.BindEnabled(Computed.From(() => newNoteText.Value.Length != 0));

See how it works? I declare a Setable, and then I have an extension method on TextBox called BindText that I can call to bind the TextBox to the Setable.

Then I have a Button I want to enable only when the TextBox is non-empty. Instead of having to say what steps to carry out and when to carry them out (“evented” imperative programming), I just declare the facts that must be true at all times, under all states the system might get into, also known as the invariants of the system.

So our pattern here is simply to define extension methods on the existing standard Windows Forms controls, with names like BindSomething, where Something is one of those properties that has an associated event SomethingChanged.

The implementation would not be particularly tricky, were it not for one thing: we will need a convenient way to unbind all the event bindings we set up. This is not always necessary, but when you have a very dynamic UI with chunks of content appearing and disappearing, or one chunk being re-used to bind to different objects, it’s essential.

We can use an approach inspired by transactions, where we capture a log of actions that will (when “played back”) unbind everything that has been bound. To see how it works, let’s start with something very simple. Here’s the implementation of a fundamental binding for practically all interesting controls: Enabled.

public static void BindEnabled(this Control control, IGetable<bool> to)
{
    BindChanged(to, () => control.Enabled = to.Value);
}

It’s a one-way binding, obviously, because the user can’t change the “enabledness” of a control. Hence we only need IGetable, and we only need to say what we’re going to do when the observable changes: no need to bind to an event on the control. Here’s BindChanged:

public static void BindChanged<T>(IGetable<T> getable, Action changed)
{
    changed();
    getable.Changed += changed;
    BindingLog.Notify(() => getable.Changed -= changed);
}

The first thing it does is run the changed action we pass in, so that the control will be initialised to match the state of getable. Then it subscribes to the Changed event and finally it “logs” an action that would, if called, unsubscribe from that event. And so how is BindingLog implemented? Why, it’s our old friend from part 2:

private static readonly ListenerStack<Action> BindingLog = new ListenerStack<Action>();

And so elsewhere, whenever we want to do some random binding and capture an action that we execute later to undo that binding, we should carry out the binding activity inside a context:

public static Action CaptureUnbind(Action bindingActivity)
{
    try
    {
        Action multicastUnbinders = null;
        Log.Push(nestedUnbinder => multicastUnbinders += nestedUnbinder);
        bindingActivity();
        return multicastUnbinders ?? EmptyAction;
    }
    finally
    {
        Log.Pop();
    }
}

[Trivia: Whenever you are building up a list of actions so that later you can loop through them all and execute them, remember that C# actually has language support for that pattern: the multicast delegate. You can say action += anotherAction and now action has been replaced by a new action that calls the original two actions.]

Usage:

var unbind = Binding.CaptureUnbind(() =>
{
    textBoxNewNote.BindText(newNoteText);

    buttonAdd.BindEnabled(Computed.From(
          () => newNoteText.Value.Length != 0));

    // Any other bindings in this batch...
});

And then to unbind:

unbind();

So, to business. Here’s version one of my simple demo UI.

notetaker2

You can type in the top text box to enter a new “note”, by clicking Add. We display the current list of notes in a checked list box. You can check items and then click Delete to delete all checked items. And you toggle selection of all/none by clicking the Select all check box. It’s a nice example because the things on the screen are related in ways that aren’t as simple as they first appear.

In persistent terms, a note is just a string. But in our UI, a note is also either selected or not. So we really should model a note like this;

public class Note
{
    public readonly ISetable<string> Text = new Setable<string>();
    public readonly ISetable<bool> IsSelected = new Setable<bool>();
}

Now, you might be tempted to “correct” this as follows, in order to do things by-the-book (what are you, the encapsulation police?):

public class Note
{
    private readonly ISetable<string> _text = new Setable<string>();
    private readonly ISetable<bool> _isSelected = new Setable<bool>();

    public ISetable<string> Text { get { return _text; } }
    public ISetable<bool> IsSelected { get { return _isSelected; } }
}

But in this simple example (and many real-world cases), it would add nothing. Each of our properties is already encapsulated behind ISetable, which gives us total flexibility in the future to change how they are implemented internally without affecting our clients. ISetable is just another way of encapsulating a mutable property, with the added bonuses that (a) we can pass around a reference to it where necessary (rather like a “property delegate”, something absent from C# itself), and most important of all (b) it has a built-in Changed event.

Now we need a little nugget of UI to represent a note in the list. I’ll do something a bit weirder than a mere CheckBox, just to demonstrate a more powerful capability. We’ll define a new Form-derived class, NoteListItemForm, which is laid out very compactly:

noteitem1

There’s a CheckBox without a label, so next to it I can put a TextBox. This will mean that the user can edit the note text directly in the list (though it will make selection a bit less intuitive – however, we’ll come back to that).

The code-behind for this mini-form is very simple:

public partial class NoteListItemForm : Form, IBindsTo<Note>
{
    public NoteListItemForm()
    {
        InitializeComponent();
        TopLevel = false;
        Visible = true;
    }

    public void Bind(Note note)
    {
        textBoxContent.BindText(note.Text);
        checkBoxIsSelected.BindChecked(note.IsSelected);
    }
}

In the constructor we make the standard changes necessary to make it suitable for adding as a child of a Panel. Then there’s just a Bind method that wires it up to a Note (thanks to the magic unbinding context we built above, there’s never a need to write a corresponding Unbind method). By the way, that Bind method implements the IBindsTo interface, which will turn out to be important in a moment.

Strange as it may seem, the rest of our code can be put very neatly in the constructor of our main Form-derived class. First we declare the list of notes:

var notes = new SetableList<Note>();

Then we have a large Panel on our main Form where we’d like the list to appear. There’s a rather nifty extension method on Panel that we can use like this:

panelSelectionList.BindForEach(notes).As<NoteListItemForm>();

It has a slightly peculiar chained declaration, just to get the most out of type inference. BindForEach only needs one direct parameter, an ISetableList<TItem>, which is the source of data. Then that returns something on which you have to call As, which only needs a type parameter. Here that is our mini-Form, but it could be any class derived from the Windows Forms Control class which implements the IBindsTo interface and has a parameter-less constructor – or to put it another way:

where TControl : Control, IBindsTo<TItem>, new()

Every time the contents of the list change, the binding automatically creates (or destroys) child controls in the panel, laying them out vertically, and calling each child control’s Bind method to set it up. (Important: this only happens when we put different Note objects in the list. Nothing has to happen here when one of the internal properties of a Note changes, because those have their own bindings.)

Next we arrange for new notes to be added by the user (which is actually the same code I used as an example above):

var newNoteText = Setable.From(string.Empty);
textBoxNewNote.BindText(newNoteText);

// 'Add' button only enabled if text box is non-empty
buttonAdd.BindEnabled(Computed.From(() => newNoteText.Value.Length != 0));

buttonAdd.Click += (s, ev) =>
{
    notes.Add(new Note { Text = { Value = newNoteText.Value } });
    textBoxNewNote.Text = string.Empty;
    textBoxNewNote.Focus();
};

Oh look! An actual explicitly wired-up event handler. Button.Click is the only kind of event we should ever have to deal with like this: it’s intrinsically imperatively by nature. Otherwise, it’s declaration everywhere, including our first Computed.

A more thorny problem is that of the Select all CheckBox, which has three states. If we only select some of the notes, the CheckBox should be “indeterminate”. But with a couple more Computeds we can declare what we want it do and it’s really very easy, even though it would be surprisingly gnarly in traditional evented-imperative code.

Firstly, lets compute ourselves a list of just those notes that are currently selected (which is going to be useful for the Delete button also):

var selectedNotes = Computed.From(() => notes.Where(n => n.IsSelected.Value).ToList());

Two things to note:

  1. Just because it’s a list, it doesn’t need to be an ISetableList. It’s just an ordinary IGetable that happens to contain a computed list as its value.
  2. It’s really important that we say ToList(), because we have to access the IsSelected property directly during the execution of the lambda we pass to Computed.From, otherwise the library can’t detect our dependency on that property. If we leave it as a lazily evaluated list, we apparently won’t be dependent on anything.

But how do come up with something we can bind to our three-state checkBoxAllNotes? There is a suitable binding extension method, BindCheckState, that supports all three states using the standard enum CheckState as the value. But what about the value we’ll bind to?

Happily there’s another trick up our sleeves: the setable computed. This essentially lets you define on-the-fly a property with custom getter and setter methods.

checkBoxAllNotes.BindCheckState(Computed.From(

    get: () => selectedNotes.Value.Count == 0
                    ? CheckState.Unchecked
                    : selectedNotes.Value.Count == notes.Count
                            ? CheckState.Checked
                            : CheckState.Indeterminate,

    set: state =>
        {
            // only pay attention when setting to a definite state
            if (state == CheckState.Indeterminate)
                return;

            foreach (var note in notes)
                note.IsSelected.Value = state == CheckState.Checked;
        }));

We’re using an overload of Computed.From that takes two parameters, get and set. I’m using named parameter syntax even though its totally redundant here, just for clarity (and because it resembles the declaration of a property).

The getter lambda literally says: “if none are selected I’m unchecked; if all are selected I’m checked; otherwise I’m indeterminate.” The setter is even simpler: it sets all the notes to be either selected or not selected, depending on whether the new state is Checked or Unchecked. If the new state happens to be Indeterminate, it does nothing.

And we don’t really need this dang CheckBox to work at all if there aren’t currently notes to select:

checkBoxAllNotes.BindEnabled(Computed.From(() => notes.Count != 0));

Now the Delete button is child’s play:

buttonDelete.BindEnabled(Computed.From(() => selectedNotes.Value.Count != 0));
buttonDelete.Click += (s, ev) => notes.RemoveAll(selectedNotes.Value);

Recall that all this is in the constructor of our main Form. To recap:

var notes = new SetableList<Note>();
            
// For each each note, make a CheckedListBoxItem
panelSelectionList.BindForEach(notes).As<NoteListItemForm>();

var newNoteText = Setable.From(string.Empty);
textBoxNewNote.BindText(newNoteText);

// Add button only enabled if text box is non-empty
buttonAdd.BindEnabled(Computed.From(() => newNoteText.Value.Length != 0));
buttonAdd.Click += (s, ev) =>
{
    notes.Add(new Note { Text = { Value = newNoteText.Value } });
    textBoxNewNote.Text = string.Empty;
    textBoxNewNote.Focus();
};

// list of currently selected notes (important: ToList to avoid lazy evaluation)
var selectedNotes = Computed.From(() => notes.Where(n => n.IsSelected.Value).ToList());

// Two-way binding
checkBoxAllNotes.BindCheckState(Computed.From(

    get: () => selectedNotes.Value.Count == 0
                    ? CheckState.Unchecked
                    : selectedNotes.Value.Count == notes.Count
                            ? CheckState.Checked
                            : CheckState.Indeterminate,

    set: state =>
        {
            // only pay attention when setting to a definite state
            if (state == CheckState.Indeterminate)
                return;

            foreach (var note in notes)
                note.IsSelected.Value = state == CheckState.Checked;
        }));

checkBoxAllNotes.BindEnabled(Computed.From(() => notes.Count != 0));

// Delete button only enabled if selection is non-empty
buttonDelete.BindEnabled(Computed.From(() => selectedNotes.Value.Count != 0));
buttonDelete.Click += (s, ev) => notes.RemoveAll(selectedNotes.Value);

You can get the code from GitHub to see the NoteTaker application in action. Next time on this channel: let’s make the UI unnecessarily complicated and powerful, so it has multiple simultaneously updating views on the same information, all of which stay mutually consistent, yet we barely have to write any more code.

Categories: Uncategorized Tags: , ,