通过依赖属性 (UWP) 更改 VisualState [英] Change VisualState through Dependency Property (UWP)

查看:29
本文介绍了通过依赖属性 (UWP) 更改 VisualState的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 UserControl 中有一个文本框,我希望该文本框有两个额外的状态,有效和无效.我的代码看起来像这样

I have a textbox inside a UserControl, I want to have two extra states for that textbox, Valid and Invalid. 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>

在代码隐藏中

  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>

在调试器上,我可以看到这条线被执行了 VisualStateManager.GoToState(mytxt, "InvalidState", false); 但是视觉状态永远不会改变,红色永远不会出现在这条线上.谁能指出我遗漏了什么?

On debugger, I can see that this line gets executed VisualStateManager.GoToState(mytxt, "InvalidState", false); But the visual state never changes and Red color never comes for that line. Can anyone please point out what I am missing?

推荐答案

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

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:

试试这个:

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.这需要父类继承INotifyPropertyChanged接口并在修改数据时调用OnPropertyChanged方法.

First, HasError defaults to false when no value is assigned. You can manually change its value, but you need to notify the UI after the change. This requires the parent class inheriting the INotifyPropertyChanged interface and calling the OnPropertyChanged method when modifying the data.

其次,修改HasError的值要在保证控件已经加载的情况下进行,否则虽然你修改了值,但是控件还没有加载,这个属性改变是无效的.

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.

谢谢.

这篇关于通过依赖属性 (UWP) 更改 VisualState的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆