Question

My question is simple: WHEN (on what event?) can I be sure that a control has fully loaded and has its states and templates also?


Why am I asking:

I'm trying to restore the state of my own WP7 control after recovering from tombstone. This control looks like a calendar in a weekly view. In this calendar you can select many items displayed as colored Rectangles.

If I select any of them, and then go to tombstone and come back to the page, it seems like my control forgot which Rectangles were selected. In fact, it did NOT forget the data itself, but the Rectangles forgot their selected state.

After recovering from tombstone, I try to select the Rectangles by setting their VisualState to "Selected" (which works in any other scenario). I found out, that it fails, because VisualStateManager can't find the "Selected" state.

I know this is tricky, because when coming back from tombstone the controls do not build exactly as in any "normal" case. (for example Bindings and Templates do not apply in the same order) But up until now I could always trust, that when FrameworkElement.Loaded fired, I had my controls ready. Now it seems like VisualState is not. (I tried to set the state from Loaded event handler, but results are the same, VisualStateManager.GoToState returns with false.)

What more can I do?

Was it helpful?

Solution

This is a tricky one! I have also experienced issues where UI events fire before the UI itself is fully constructed, see this blog post for an example. My general approach to this is to handle the LayoutUpdated event, which fires each time the visual tree is updated. You will find that this event fires multiple times, both before and after the Loaded event.

When the Layoutupdated event fires, you can check whether the visual state change has worked, if so, no longer handle the event. If not, keep trying!

Within your loaded event, try the following:

 // try to set the state
  if (VisualStateManager.GoToState(myControl, "myState") == false)
  {
    // if failed, wait for the next LayoutUpdated event
    EventHandler updateHandler = null;
    updateHandler = (s, e2) =>
    {
      if (VisualStateManager.GoToState(myControl, "myState") == false) 
      {
        myControl.LayoutUpdated -= updateHandler;
      }
    };
    myControl.LayoutUpdated += updateHandler;
  }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top