locked
How programmatically create and add a VisualStateGroup to a Xaml control?

    Question

  • My test App UI is currently 100% code (no Xaml used at all). My understanding is that while Microsoft would prefer developers to build their UI's using Xaml, they have also said that UI's can be built entirely in code.

    For example how would I add my own ControlTemplate to an instance of 'Windows::UI::Xaml::Controls::Button' programmatically using C++/CX. This ControlTemplate would have VisualStates for "CommonStates(Normal, PointerOver, Pressed, Disabled)" and for "FocusStates(Focused, Unfocused, PointerFocused)" similar to those defined in 'winrt/xam/design/generics.xaml'.

    I cannot determine how to define the Name properties (or equivalent) for the VisualStateGroup and VisualState classes (they have read-only
    Name properties).

    Is this possible in C++/CX ? If so could you please point me in the right direction, Thanks.

    Tuesday, April 16, 2013 2:05 PM

Answers

  • Hi Keith,

    I don't believe you can set up VisualStates without Xaml. As you note, the Name property is read-only and comes from the Xaml-only x:Name attribute (this is called out in the VisualStateGroup and VisualState docs).

    In most cases this doesn't matter: the x:Name is used to declare variables based on the Xaml and generally isn't needed if you are creating the objects directly in code. The VisualState Name is an exception though, since you need to use it to call VisualStateManager::GoToState.

    This means that you will need to use Xaml for enough of the ControlTemplate to declare the VisualStates. I haven't tried it, but I suspect that loading just the base ControlTemplate's Xaml with a XamlReader should be sufficient. Once you have that loaded you can fill in the rest of the template programmatically.

    --Rob

    Tuesday, April 16, 2013 5:45 PM
    Owner
  • Rob,

    I was already working on the XamlReader solution.

    It does work - I can define a Platform::String dynamically with Xaml code created either programmatically or partially loaded from helper files and then I used:

    //xaml string contains full Xaml markup for <Style TargetType=\"Button\">
    //including VisualStateGroups, VisualStates and StoryBoards.
     
    Platform::Object^ xamlObj = Windows::UI::Xaml::Markup::XamlReader::Load(xaml);
    Windows::UI::Xaml::Style^ xamlStyle;
    xamlStyle = dynamic_cast<Windows::UI::Xaml::Style^>(xamlObj);
    if (xamlStyle != nullptr)
    {
       _theView->Style = xamlStyle;
    }
    

    Hopefully the VisualState Name property will be made writable in the future, but this workaround may suffice in the short term.

    Thanks.

    • Marked as answer by Keith Slack Tuesday, April 16, 2013 6:27 PM
    Tuesday, April 16, 2013 6:26 PM

All replies

  • Hi Keith,

    I don't believe you can set up VisualStates without Xaml. As you note, the Name property is read-only and comes from the Xaml-only x:Name attribute (this is called out in the VisualStateGroup and VisualState docs).

    In most cases this doesn't matter: the x:Name is used to declare variables based on the Xaml and generally isn't needed if you are creating the objects directly in code. The VisualState Name is an exception though, since you need to use it to call VisualStateManager::GoToState.

    This means that you will need to use Xaml for enough of the ControlTemplate to declare the VisualStates. I haven't tried it, but I suspect that loading just the base ControlTemplate's Xaml with a XamlReader should be sufficient. Once you have that loaded you can fill in the rest of the template programmatically.

    --Rob

    Tuesday, April 16, 2013 5:45 PM
    Owner
  • Rob,

    I was already working on the XamlReader solution.

    It does work - I can define a Platform::String dynamically with Xaml code created either programmatically or partially loaded from helper files and then I used:

    //xaml string contains full Xaml markup for <Style TargetType=\"Button\">
    //including VisualStateGroups, VisualStates and StoryBoards.
     
    Platform::Object^ xamlObj = Windows::UI::Xaml::Markup::XamlReader::Load(xaml);
    Windows::UI::Xaml::Style^ xamlStyle;
    xamlStyle = dynamic_cast<Windows::UI::Xaml::Style^>(xamlObj);
    if (xamlStyle != nullptr)
    {
       _theView->Style = xamlStyle;
    }
    

    Hopefully the VisualState Name property will be made writable in the future, but this workaround may suffice in the short term.

    Thanks.

    • Marked as answer by Keith Slack Tuesday, April 16, 2013 6:27 PM
    Tuesday, April 16, 2013 6:26 PM