I've created a UserControl, PortStatusButton, that contains nothing but a RadButton for which I've modified its standard style to incorporate my own VisualStateGroup with its VisualStates. Its purpose is to be a multistate button with logic based on the values of several of its properties. I have written a custom VisualStateManager to process that logic. I have placed the PortStatusButton into the ItemTemplate of a RadListBox and bound its properties to data in my Model.
The basic method I've used to incorporate my visual states into the button is to create a separate VisualStateGroup and then have my VisualStateManager watch for a call to GoToStateCore for a CommonStates.Normal VisualState. I then check to see what state my button should be in and then call GoToState to go to my desired state. This allows me to have the PortStatusButton show my states, but still let the RadButton control the overall functioning of the button.
It's all working quite well, with one exception. When the PortStatusButton first appears, it fails to display my correct VisualState, but displays the CommonStates.Normal state instead. I think I know why and I'd like to ask you to verify that I'm correct and suggest what I might do about it.
The mode of failure is that the first time a property gets set in PortStatusButton, the UpdateButtonAppearance method that is called by its OnPropertyChanged handler fails to obtain a reference to the the current state of my VisualStateGroup because it can't find the child Grid of the RadButton that contains the VisualStateManager. Thus, it never calls GoToState because it doesn't know where to go, and the RadButton first displays in its CommonStates.Normal state.
The data that is feeding the bound PortStatusButton properties is coming from my ViewModel, which is defined as the DataContext in the main Grid that contains the RadListBox, and which loads the source collection in its constructor. My suspicion is that as each PortStatusButton is instantiated by the RadListBox, the Grid in the RadButton's control template has not yet been instantiated, so it's not yet there to be found. By the time the user starts clicking on the buttons, the Grid has been instantiated and the PortStatusButtons will function as they should.
Is that correct?
What would you suggest I do to allow the buttons to display my correct state when they first appear?
I have included excerpts from my code below:
First, excerpt from my PortStatusButton xaml:
And an excerpt from my PortStatusButton code behind:
And the custom VisualStateManager:
And an excerpt from the control containing the RadListBox: