繁体   English   中英

通过依赖属性 (UWP) 更改 VisualState

[英]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 永远不会改变,红色永远不会出现在这条线上。 谁能指出我错过了什么?

我检查了你的代码,你的控件本身没有问题,问题在于MainPageHasError变量的赋值时机:

尝试这个:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM