Sometimes the data you want to show is not available (like returned from the server or database) until several seconds after your page has loaded and rendered. This is especially true if you call your data in a background/async process that frees up your UI to render without a hang.
Make sense so far?
Now create a binding; let's say something like this:
<TextBlock Text="{x:Bind ViewModel.User.FirstName}" />
The value of your ViewModel property in your code-behind will have a real value and will bind just fine. Your User, on the other hand, will not have a value because it is not returned from the server yet. As a result neither that nor the FirstName property of the User can be displayed, right?
Then your data is updated.
You would think that your binding would automatically update when you set the value of the User object to a real object. Especially if you took the time to make it a INotifyPropertyChanged property, right? That would be true with traditional {Binding} because the default binding mode is OneWay.
What is the OneWay binding mode?
The OneWay binding mode means that you can update your backend model properties that implement INotifyPropertyChanged and the UI element bound to that property will reflect the data/value change. It's wonderful.
Why does it not work?
It is NOT because {x:Bind} does not support Mode=OneWay, it is because it defaults to Mode=OneTime. To recap, traditional {Binding} defaults to Mode=OneWay and compiled {x:Bind} defaults to Mode=OneTime.
What is the OneTime binding mode?
The OneTime binding mode means that you bind to the underlying model only once, at the time of load/render of the UI element with the binding. This means that if your underlying data is not yet available, it cannot display that data and once the data is available it will not display that data. Why? Because OneTime does not monitor INotifyPropertyChanged. It only reads when it loads.
Modes (from MSDN): For OneWay and TwoWay bindings, dynamic changes to the source don't automatically propagate to the target without providing some support from the source. You must implement the INotifyPropertyChanged interface on the source object so that the source can report changes through events that the binding engine listens for. For C# or Microsoft Visual Basic, implement System.ComponentModel.INotifyPropertyChanged. For Visual C++ component extensions (C++/CX), implement Windows::UI::Xaml::Data::INotifyPropertyChanged.
How to solve this problem?
There are a few ways. The first and easiest is to change your binding from ="{x:Bind ViewModel.User.FirstName}
to ="{x:Bind ViewModel.User.FirstName, Mode=OneWay}
. Doing this will monitor for INotifyPropertyChanged events.
This is the right time to warn you that using OneTime by default is one of the many ways {x:Bind} tries to improve performance of binding. That's because OneTime is the fastest possible with the least memory reqs. Changing your binding to OneWay undermines this, but it might be necessary for your app.
The other way to fix this problem and still maintain the performance benefits that come out of the box with {x:Bind} is to call Bindings.Update();
after your view model has completely prepared your data for presenting. This is easy if your work is async - but, like your sample above, if you can't be sure a timer might be your only viable option.
That sucks of course because a timer implies clock time, and on slow devices like a phone, that clock time might not properly apply. This is something every developer will have to work out specific to their app - that is to say, when is your data fully loaded and ready?
I hope this explains what is happening.
Best of luck!