When a Correspondence application starts up, it doesn’t need to immediately load data from storage. It can complete its data binding and render an empty view. Then, when the data is loaded, it can update the view. This results in quicker load times and more responsive applications. But it also means that you sometimes have to take one extra step to ensure the value of a property or result of a query.
Delayed load for more fluid UI
Let’s start with a simple model. An individual is identified by their anonymous Windows Live ID. The user can change their name. Here’s the model:
fact Individual {
key:
string anonymousId;
mutable:
publish string name;
}
We’ll inject the individual into a view model. From there, we expose the name property for data binding.
public class MainViewModel
{
private Individual _individual;
public MainViewModel(Individual individual)
{
_individual = individual;
}
public string Name
{
get { return _individual.Name; }
set { _individual.Name = value; }
}
}
When the application starts up, Correspondence won’t wait for the name to load from storage before displaying the view. It will just return a null during the initial data binding. After the name has loaded asynchronously, it will fire property changed and update the view.
When the user enters a new name, the property setter asynchronously starts the process of writing the new value. It returns before that process is finished so that the UI can be more responsive. When dealing with data binding and user interaction, this behavior is beneficial. The UI renders more quickly and fluidly, even if the data fills in just a fraction of a second later.
Delayed load is not so good for code
But when dealing with code, this behavior is unexpected. For example:
_flynn.FavoriteColor = "Blue";
// It's still blank.
Assert.AreEqual(null, _flynn.FavoriteColor.Value);
If I’ve never read the property before, it will return null. It will start loading the value asynchronously, but by then my code has already moved on. It won’t respond to a PropertyChanged notification when the value finishes loading.
Ensure that a property is loaded
You don’t want the UI to wait for the value to finish loading. That would just cause stutter. But you do want code to wait. So in code, you should call the “Ensure()” method. Ensure will block until the property has finished loading.
_flynn.FavoriteColor = "Blue";
// Ensure that the value is loaded.
Assert.AreEqual("Blue", _flynn.FavoriteColor.Ensure().Value);
Ensure that query results are loaded
Ensure also works with queries. By default, a query will return an empty collection while the result loads asynchronously. But when you need to make a decision based on the results of a query, you need to Ensure that they’ve finished loading.
TaskList taskList = individual.TaskLists.Ensure().FirstOrDefault();
if (taskList == null)
taskList = individual.CreateTaskList();
Task task = taskList.AddTask();
Without the call to Ensure, this code will create a new task list every time the application starts.
Because Ensure blocks, do not call it in a view model property getter. You don’t want to block the UI. But it is perfectly valid in a view model property setter. The user has already performed an action, and they won’t perceive the momentary pause while the query or property loads. It’s also appropriate to use in background code that is not related to the view model at all. If you use Ensure in the right places, you can have the consistent behavior that code needs while still getting the responsive UI that the user desires.