简体   繁体   中英

UWP VisualStateManager.GoToState Always Returns False

I am trying to use visual states to mark a TextBox input as invalid (by changing its border color to red) during input validation when a user submits a form the TextBox is a part of. I have the following code:

XAML

<Page.Resources>

    <!-- Other resources omitted for brevity -->

    <Flyout x:Key="NewTimeBlockFlyout">
        <StackPanel>

            <!-- Other stuff here omitted for brevity -->

            <TextBox Margin="5"
                     Header="Name"
                     x:Name="NewTimeBlockNameTextBox">
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup>
                        <VisualState x:Name="Default"></VisualState>
                        <VisualState x:Name="Invalid">
                            <VisualState.Setters>
                                <Setter Target="NewTimeBlockNameTextBox.Background" Value="Red"></Setter>
                            </VisualState.Setters>
                        </VisualState>
                   </VisualStateGroup>
               </VisualStateManager.VisualStateGroups>
            </TextBox>

        <!-- The rest of the form omitted for brevity -->

        <Button x:Name="CreateTimeBlockButton"
                Grid.Column="0"
                Margin="0,0,2,0"
                HorizontalAlignment="Stretch"
                Tapped="CreateTimeBlockButton_Tapped">Create</Button>
        </StackPanel>
    </Flyout>
</Page.Resources>

Note: This is on a XAML Page . I am NOT using a custom control.

C#

private void CreateTimeBlockButton_Tapped(object sender, TappedRoutedEventArgs e)
{
    // Validate the input.
    if (String.IsNullOrWhiteSpace(this.NewTimeBlockNameTextBox.Text))
    {
        // These two lines of code confirm the visual state named "Invalid" does exist on the textbox.
        //List<VisualStateGroup> m = VisualStateManager.GetVisualStateGroups(this.NewTimeBlockNameTextBox).ToList();
        //List<VisualState> c = m.FirstOrDefault().States.ToList();

        // Assignment to bool just used to inspect the return value for debugging.
        bool did = VisualStateManager.GoToState(this.NewTimeBlockNameTextBox, "Invalid", false);
    }
}

Problem

No matter what I try, the call to VisualStateManager.GoToState() is always returning false.

Things I have tried:

Here is the relevant documentation from Microsoft .

As seen in the C# code above, I have verified the visual state "Invalid" does exist, as expected, on the "NewTimeBlockNameTextBox" control.

I have seen several solutions including here , and here that suggest moving the <VisualStateManager.VisualStateGroups> tag in the XAML to outside of the TextBox , or to the root of the Page . Neither have worked for me.

I have also seen these two solutions here and here , but neither seemed relevant to my situation, as both seem to have issues related to things I am not doing.

I can reproduce your issue. You need to place <VisualStateManager.VisualStateGroups> outside the TextBox and skip status through VisualStateManager.GoToState(this, "Invalid", false); Please refer to the following code.

Xaml code:

<Page
   ……
   Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <StackPanel>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="Default"></VisualState>
                <VisualState x:Name="Invalid">
                    <VisualState.Setters>
                        <Setter Target="NewTimeBlockNameTextBox.BorderBrush" Value="Red"></Setter>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <TextBox  Margin="5"
                     Header="Name"
                     x:Name="NewTimeBlockNameTextBox" >
        </TextBox>       
     
            <Button x:Name="CreateTimeBlockButton"
                Grid.Row="1"
                Margin="0,0,2,0"
                HorizontalAlignment="Stretch"
                Tapped="CreateTimeBlockButton_Tapped">Create</Button>

        </StackPanel>
</Page>

Code behind:

   private void CreateTimeBlockButton_Tapped(object sender, TappedRoutedEventArgs e)
    {                         
        bool a = VisualStateManager.GoToState(this, "Invalid", false);         
    }

Updated:

For using VisualStateManager.GoToState(), which always be done by changing its controltemplate.

You could right click the textbox in XAML designer, then select the option Edit a Template -> Edit a Copy , here you will see the default textbox style placed in <Page.Resources> </Page.Resources> tag.

<Style x:Key="TextBoxStyle1" TargetType="TextBox">
……
<Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TextBox">
                    ……
                           <VisualStateManager.VisualStateGroups>
……
                             <VisualState x:Name="TestState">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="red"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <ContentPresenter x:Name="HeaderContentPresenter" …/>
<Border x:Name="BorderElement" …/>
……
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
  </Style>

As you can see, you could place custom state in its template, then you could use “ VisualStateManager.GoToState(NewTimeBlockNameTextBox, "TestState", false); ” to skip state.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM