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.
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>
So in C# code now I've created a custom TextBox class.
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.
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.
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;
}
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.
This is a Windows 8 application using WinRT XAML and C#.