[英]Change VisualState through Dependency Property (UWP)
I have a textbox inside a UserControl, I want to have two extra states for that textbox, Valid and Invalid.我在 UserControl 中有一个文本框,我希望该文本框有两个额外的状态,有效和无效。 My code looks like this
我的代码看起来像这样
<UserControl.Resources>
<Style TargetType="TextBox" x:Key="ExtendeTextBoxStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ValidationState">
<VisualState x:Name="InvalidState">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ValidState"></VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{TemplateBinding PlaceholderText}" Visibility="Collapsed" x:Name="HeaderText" Foreground="{ThemeResource ColorCompany}" ></TextBlock>
<Border x:Name="BackgroundElement"
Grid.Row="2"
Background="{TemplateBinding Background}"
Margin="{TemplateBinding BorderThickness}"
Grid.ColumnSpan="2"
Grid.RowSpan="1"/>
<Line x:Name="BorderElement" Stroke="{ThemeResource ColorCompany}" X2="10000" Grid.Row="3" Grid.ColumnSpan="2"
StrokeThickness="{ThemeResource TextBoxStrokeThickness}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<TextBox x:Name="txtbox" Width="438" Height="56" Style="{StaticResource ExtendeTextBoxStyle}"
PlaceholderText="{x:Bind PlaceholderText, Mode=OneWay}" ></TextBox>
</Grid>
And in code-behind在代码隐藏中
public bool HasError
{
get { return (bool)GetValue(HasErrorProperty); }
set { SetValue(HasErrorProperty, value); }
}
/// <summary>
/// This is a dependency property that will indicate if there's an error.
/// This DP can be bound to a property of the VM.
/// </summary>
public static readonly DependencyProperty HasErrorProperty =
DependencyProperty.RegisterAttached("HasError", typeof(bool), typeof(EditTextControl), new PropertyMetadata(false, HasErrorUpdated));
// This method will update the Validation visual state which will be defined later in the Style
private static void HasErrorUpdated(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
EditTextControl textBox = d as EditTextControl;
Grid sds = textBox.Content as Grid;
var mytxt = sds.Children.FirstOrDefault() as TextBox;
if (textBox != null)
{
if (textBox.HasError)
VisualStateManager.GoToState(mytxt, "InvalidState", false);
else
VisualStateManager.GoToState(mytxt, "ValidState", false);
}
}
And I am calling this usercontrol inside my page like this我像这样在我的页面中调用这个用户控件
<editors1:EditTextControl HasError="{x:Bind HasError, Mode=OneWay}"></editors1:EditTextControl>
On debugger, I can see that this line gets executed VisualStateManager.GoToState(mytxt, "InvalidState", false);
在调试器上,我可以看到这条线被执行了
VisualStateManager.GoToState(mytxt, "InvalidState", false);
But the visual state never changes and Red color never comes for that line.但是视觉上的 state 永远不会改变,红色永远不会出现在这条线上。 Can anyone please point out what I am missing?
谁能指出我错过了什么?
I checked your code, there is nothing wrong with your control itself, the problem lies in the assignment timing of the HasError
variable in the MainPage
:我检查了你的代码,你的控件本身没有问题,问题在于
MainPage
中HasError
变量的赋值时机:
Try this:尝试这个:
Xaml Xaml
<Grid>
<editors1:EditTextControl HasError="{x:Bind HasError, Mode=OneWay}"
Loaded="EditTextControl_Loaded"/>
</Grid>
Xaml.cs Xaml.cs
public sealed partial class MainPage : Page,INotifyPropertyChanged
{
private bool _hasError;
public bool HasError
{
get => _hasError;
set
{
_hasError = value;
OnPropertyChanged();
}
}
public MainPage()
{
this.InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
private void EditTextControl_Loaded(object sender, RoutedEventArgs e)
{
HasError = true;
}
}
First, HasError
defaults to false when no value is assigned.首先,当没有赋值时,
HasError
默认为 false。 You can manually change its value, but you need to notify the UI after the change.您可以手动更改其值,但您需要在更改后通知 UI。 This requires the parent class inheriting the
INotifyPropertyChanged
interface and calling the OnPropertyChanged
method when modifying the data.这就需要父 class 继承
INotifyPropertyChanged
接口并在修改数据时调用OnPropertyChanged
方法。
Secondly, changing the value of HasError
should be done when ensuring that the control has been loaded, otherwise although you have changed the value, but the control has not been loaded, this property change is invalid.其次,更改
HasError
的值应该在确保控件已经加载的情况下进行,否则虽然你改变了值,但是控件还没有加载,这个属性的改变是无效的。
Thanks.谢谢。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.