问题描述
我正在尝试在 WinRT XAML 中创建自定义文本框.当输入的数据出现错误时,我希望文本框突出显示红色.
I'm trying to create a custom textbox in WinRT XAML. I want the textbox to highlight red when there is an error with the entered data.
首先,我修改了 TextBox Temple,并添加了一个新的 VisualStateGroup(CustomStates - 带有 HasError 状态),我还更改了 Focused 组:
So first off I've modified the TextBox Temple and I've added a new VisualStateGroup (CustomStates - with HasError State) and I've also change the Focused group:
<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 类.
So in C# code now I've created a custom TextBox class.
我添加了一个依赖属性调用 HasError,它只是一个用于保存错误状态的布尔值.当此值更改时,将调用 GoToState 方法,该方法将状态设置为我的 HasError 状态.
I've added a Dependency property call HasError which is just a bool to hold the error state. When this value changes the GoToState method is then called which sets the state to my HasError state.
我添加了一个委托和事件,用于验证是否发生了错误.
I've added a delegate and event, which I use to validate if an error has happened.
最后,我覆盖了 OnLostFocus 和 OnGotFocus 方法.OnLostFocus 调用我的委托,OnGotFocus 重置错误状态
Finally I've overridden the OnLostFocus and OnGotFocus methods. OnLostFocus call my delegate and OnGotFocus reset the error state
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);
}
}
所以,这是我的文本框.
So, that's my textbox.
现在在应用程序中,我将一个文本框的实例添加到表单中并订阅 ValidateText 事件,在该事件中仅用于测试我将 HasError 属性设置为 true.
Now in the application I add an instance of a textbox to the form and subscribe to the ValidateText event and in that event just for testing I set the HasError property to true.
<MyTextBox x:Name="textTest" ValidateText="textTest_ValidateText" />
private void textTest_ValidateText(object sender, RoutedEventArgs e)
{
textTest.HasError = true;
}
所以,现在当我运行它并且焦点从文本框中丢失时,它突出显示为红色,这正是我想要的.但是,如果我再次选择相同的文本框并再次将焦点移开,则不会应用 HasError 状态,并且文本框只会在其默认视图中显示回来.HasError 代码正在运行,所以我不明白为什么没有显示红色错误颜色!??!?!
So, now when I run this and the focus is lost from the textbox it is highlighted red which is just what I want. However, if I select the same textbox again and move the focus away again the HasError state isn't applied and the textBox just shows back in it's default view. The HasError code is running so I can't understand why the red error color isn't showing!??!?!
任何人都可以帮忙吗?我希望这一切都有意义.
Anyway can anybody help? I hope it all makes sense.
这是一个使用 WinRT XAML 和 C# 的 Windows 8 应用程序.
This is a Windows 8 application using WinRT XAML and C#.
推荐答案
您不应使用来自不同组的两种状态来为同一属性设置动画.在这种情况下,这不起作用,因为您已经第二次处于 HasError 状态(您永远不会离开该状态).
You should not use two states from different groups to animate the same property. In this case, this is not working because you already are in the state HasError the second time (you never leave that state).
一个解决方案是向您的CustomStates"组添加一个名为NoError"的额外状态.
A solution is to add an extra state to your "CustomStates" group called "NoError".
添加视觉元素(例如只有您的状态才会动画的附加矩形或边框).然后,您必须从 OnGoFocus 覆盖中触发 NoError 状态.
Add visual element (such as an additional rectangle or border that only your state will animate). Then you'll have to trigger the NoError state from OnGoFocus override.
这篇关于未在 WinRT XAML 中设置自定义 VisualState的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!