[英]Change VisualState through Dependency Property (UWP)
我在 UserControl 中有一個文本框,我希望該文本框有兩個額外的狀態,有效和無效。 我的代碼看起來像這樣
<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>
在代碼隱藏中
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);
}
}
我像這樣在我的頁面中調用這個用戶控件
<editors1:EditTextControl HasError="{x:Bind HasError, Mode=OneWay}"></editors1:EditTextControl>
在調試器上,我可以看到這條線被執行了VisualStateManager.GoToState(mytxt, "InvalidState", false);
但是視覺上的 state 永遠不會改變,紅色永遠不會出現在這條線上。 誰能指出我錯過了什么?
我檢查了你的代碼,你的控件本身沒有問題,問題在於MainPage
中HasError
變量的賦值時機:
嘗試這個:
Xaml
<Grid>
<editors1:EditTextControl HasError="{x:Bind HasError, Mode=OneWay}"
Loaded="EditTextControl_Loaded"/>
</Grid>
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;
}
}
首先,當沒有賦值時, HasError
默認為 false。 您可以手動更改其值,但您需要在更改后通知 UI。 這就需要父 class 繼承INotifyPropertyChanged
接口並在修改數據時調用OnPropertyChanged
方法。
其次,更改HasError
的值應該在確保控件已經加載的情況下進行,否則雖然你改變了值,但是控件還沒有加載,這個屬性的改變是無效的。
謝謝。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.