【问题标题】:Custom VisualState not being set in WinRT XAML未在 WinRT XAML 中设置自定义 VisualState
【发布时间】:2018-03-24 13:02:07
【问题描述】:

我正在尝试在 WinRT XAML 中创建自定义文本框。当输入的数据出现错误时,我希望文本框突出显示红色。

所以首先我修改了 TextBox Temple,添加了一个新的 VisualStateGroup(CustomStates - 带有 HasError 状态),我还更改了焦点组:

<Style TargetType="TextBox">
....
<VisualStateGroup x:Name="CommonStates">
    <VisualState x:Name="Focused">
        <Storyboard>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
                <DiscreteObjectKeyFrame KeyTime="0" Value="Blue" />
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderThickness">
                <DiscreteObjectKeyFrame KeyTime="0" Value="2" />
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement" Storyboard.TargetProperty="Background">
                <DiscreteObjectKeyFrame KeyTime="0" Value="Blue" />
            </ObjectAnimationUsingKeyFrames>
            <DoubleAnimation Storyboard.TargetName="BackgroundElement" Storyboard.TargetProperty="Opacity" Duration="0" To="0.2" />
         </Storyboard>
     </VisualState>
 </VisualStateGroup>
    <VisualStateGroup x:Name="CustomStates">
         <VisualState x:Name="HasError">
             <Storyboard>
                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
                 </ObjectAnimationUsingKeyFrames>
                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderThickness">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="2" />
                 </ObjectAnimationUsingKeyFrames>
                 <ObjectAnimationUsingKeyFrames  Storyboard.TargetName="BackgroundElement" Storyboard.TargetProperty="Background">
                     <DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
                 </ObjectAnimationUsingKeyFrames>
                 <DoubleAnimation Storyboard.TargetName="BackgroundElement" Storyboard.TargetProperty="Opacity" Duration="0" To="0.2" />
             </Storyboard>
        </VisualState>
   </VisualStateGroup>
</Style>

所以现在我在 C# 代码中创建了一个自定义 TextBox 类。

我添加了一个 Dependency 属性调用 HasError,它只是一个用于保存错误状态的布尔值。当这个值改变时,就会调用 GoToState 方法,将状态设置为我的 HasError 状态。

我添加了一个委托和事件,用于验证是否发生了错误。

最后我重写了 OnLostFocus 和 OnGotFocus 方法。 OnLostFocus 调用我的委托,OnGotFocus 重置错误状态

public class MyTextBox : TextBox
{
    public delegate void ValidateTextHandler(object sender, RoutedEventArgs e);

    public event ValidateTextHandler ValidateText = delegate { };

    public bool HasError
    {
        get { return (bool)GetValue(HasErrorProperty); }
        set { SetValue(HasErrorProperty, value); }
    }

    public static readonly DependencyProperty HasErrorProperty = DependencyProperty.Register("HasError", typeof(bool), typeof(MyTextBox), new  PropertyMetadata(false, HasErrorChangedCallback));

    private static void HasErrorChangedCallback(DependencyObject sender,  DependencyPropertyChangedEventArgs e)
    {
        MyTextBox textBox = sender as MyTextBox;

        textBox.GoToState(true);
    }

    void GoToState(bool useTransitions)
    {
        if (HasError)
        {                
            VisualStateManager.GoToState(this, "HasError", useTransitions);                
        }
    }

    protected override void OnGotFocus(RoutedEventArgs e)
    {
        HasError = false;
        base.OnGotFocus(e);
    }

    protected override void OnLostFocus(RoutedEventArgs e)
    {
        ValidateText(this, e);
        base.OnLostFocus(e);
    }
}

所以,这是我的文本框。

现在在应用程序中,我将一个文本框的实例添加到表单并订阅 ValidateText 事件,在该事件中,我将 HasError 属性设置为 true。

<MyTextBox x:Name="textTest" ValidateText="textTest_ValidateText" />

private void textTest_ValidateText(object sender, RoutedEventArgs e)
{
    textTest.HasError = true;
}        

所以,现在当我运行它并且焦点从文本框中丢失时,它以红色突出显示,这正是我想要的。但是,如果我再次选择相同的文本框并再次将焦点移开,则不会应用 HasError 状态,并且文本框只会显示在其默认视图中。 HasError 代码正在运行,所以我不明白为什么没有显示红色错误颜色!??!?!

任何人都可以帮忙吗?我希望这一切都有意义。

这是一个使用 WinRT XAML 和 C# 的 Windows 8 应用程序。

【问题讨论】:

    标签: c# wpf windows-store-apps winrt-xaml visualstatemanager


    【解决方案1】:

    您不应使用来自不同组的两种状态来为同一属性设置动画。在这种情况下,这不起作用,因为您已经第二次处于 HasError 状态(您永远不会离开该状态)。

    一种解决方案是向您的“CustomStates”组添加一个名为“NoError”的额外状态。

    添加视觉元素(例如只有您的状态才会动画的附加矩形或边框)。然后你必须从 OnGoFocus 覆盖触发 NoError 状态。

    【讨论】:

    • 是的,是的,是的,是的!谢谢!!现在可以享用了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2016-01-14
    • 2018-06-02
    • 1970-01-01
    相关资源
    最近更新 更多