动画化以编程方式创建的 xaml 对象的翻译

Posted

技术标签:

【中文标题】动画化以编程方式创建的 xaml 对象的翻译【英文标题】:Animating the translation of a programmatically created xaml object 【发布时间】:2021-12-15 00:20:13 【问题描述】:

最初我是直接在 nInput 上完成的,一切正常。 然后我尝试将其移动到克隆对象(cloneInputForAnimation),但出现此错误:

System.InvalidOperationException:名称“TextBoxAnim”不能 在“System.Windows.Controls.TextBox”的命名空间中找到

XAML:

<TextBox x:Name="nInput" MaxLength="17" PreviewTextInput="numberValidationTextBox" Grid.Column="0"
         Height="80" Width="240"
         Foreground="White" Background="#202020"
         HorizontalAlignment="Left" BorderThickness="0"
         HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
         FontSize="25">
    <TextBox.RenderTransform>
        <TranslateTransform x:Name="TextBoxAnim" />
    </TextBox.RenderTransform>
    
    <TextBox.Resources>
        <Storyboard x:Key="myStoryboardY" x:Name="myStoryboardY">
            <DoubleAnimation
                Storyboard.TargetName="TextBoxAnim"
                x:Name="myDoubleAnimationY"
                Storyboard.TargetProperty="Y"
                Duration="0:0:0.8"
                />
        </Storyboard>
        <Storyboard x:Key="myStoryboardX" x:Name="myStoryboardX">
            <DoubleAnimation
                Storyboard.TargetName="TextBoxAnim"
                x:Name="myDoubleAnimationX"
                Storyboard.TargetProperty="X"
                Duration="0:0:0.8"
            />
        </Storyboard>
        <Storyboard x:Key="myStoryboardWidth" x:Name="myStoryboardWidth">
            <DoubleAnimation
                Storyboard.TargetName="nInput"
                x:Name="myDoubleAnimationWidth"
                Storyboard.TargetProperty="(TextBox.Width)"
                Duration="0:0:0.8"
            />
        </Storyboard>
        <Storyboard x:Key="myStoryboardHeight" x:Name="myStoryboardHeight">
            <DoubleAnimation
                Storyboard.TargetName="nInput"
                x:Name="myDoubleAnimationHeight"
                Storyboard.TargetProperty="(TextBox.Height)"
                Duration="0:0:0.8"
            />
        </Storyboard>
    </TextBox.Resources>
</TextBox>

C#:

//I clone the input box to perform the animation
            TextBox cloneInputForAnimation = CloneXaml(nInput);
            UserInteraction.Children.Add(cloneInputForAnimation);
            
            //Removing text from the realInput
            nInput.Text = "";

            //nInput.IsEnabled = false;
            
            //Creating a new object which is the one that will remain after the animation
            TextBox targetInput = CloneXaml(cloneInputForAnimation);
            targetInput.Visibility = Visibility.Hidden;
            targetInput.Width = Double.NaN;
            targetInput.Height = 50;
            nList.Children.Add(targetInput);
            
            //Obtaining the destination point
            Point targetPosition = targetInput.TransformToAncestor(rootView).Transform(new Point(0, 0));

            //Obtaining the current point
            Point currentPos = cloneInputForAnimation.TransformToAncestor(rootView).Transform(new Point(0, 0));

            //Calculating the translation to do to reach targetPosition
            Vector translateToDo = targetPosition - currentPos;
            
            //Obtaining storyboard and anim for x, y, width, height of cloneInputForAnimation (I can't use x:Name because is an element created programmatically)
            Storyboard myStoryY = cloneInputForAnimation.Resources["myStoryboardY"] as Storyboard;
            Storyboard myStoryX = cloneInputForAnimation.Resources["myStoryboardX"] as Storyboard;
            Storyboard myStoryHeight = cloneInputForAnimation.Resources["myStoryboardHeight"] as Storyboard;
            Storyboard myStoryWidth = cloneInputForAnimation.Resources["myStoryboardWidth"] as Storyboard;
            DoubleAnimation myAnimY = myStoryY.Children[0] as DoubleAnimation;
            DoubleAnimation myAnimX = myStoryX.Children[0] as DoubleAnimation;
            DoubleAnimation myAnimHeight = myStoryHeight.Children[0] as DoubleAnimation;
            DoubleAnimation myAnimWidth = myStoryWidth.Children[0] as DoubleAnimation;
            
            myAnimY.To = translateToDo.Y;
            myAnimX.To = translateToDo.X;

            myAnimHeight.To = targetInput.ActualHeight;
            myAnimWidth.To = targetInput.ActualWidth;

            cloneInputForAnimation.BeginStoryboard(myStoryY);
            cloneInputForAnimation.BeginStoryboard(myStoryX);
            cloneInputForAnimation.BeginStoryboard(myStoryHeight);
            cloneInputForAnimation.BeginStoryboard(myStoryWidth);

C# CloneXaml:

        public static T CloneXaml<T>(T source)
        
            string xaml = XamlWriter.Save(source);
            StringReader sr = new StringReader(xaml);
            XmlReader xr = XmlReader.Create(sr);
            return (T)XamlReader.Load(xr);
        

抱歉,这是我使用 WPF 的第一步,所以代码可能会有很多问题。

【问题讨论】:

【参考方案1】:

好的,正如我想象的那样,我使用了一种完全错误的方法。 这是我到达的工作版本。 XAML:

<TextBox x:Name="nInput" MaxLength="17" PreviewTextInput="numberValidationTextBox" Grid.Column="0"
                         Height="80" Width="240"
                         Foreground="White" Background="#202020"
                         HorizontalAlignment="Left" BorderThickness="0"
                         HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
                         FontSize="25">
                    
                    <TextBox.Resources>
                        <Style TargetType="x:Type Border">
                            <Setter Property="CornerRadius" Value="12" />
                        </Style>
                    </TextBox.Resources>
                </TextBox>

C#:

            Duration animDuration = new Duration(new TimeSpan(0, 0 ,0, 0,800));
            //I clone the input box to perform the animation
            TextBox cloneInputForAnimation = CloneXaml(nInput);
            UserInteraction.Children.Add(cloneInputForAnimation);

            //Removing text from the realInput
            nInput.Text = "";

            //nInput.IsEnabled = false;

            //Creating a new object wich is the one that will remain after the animation
            TextBox targetInput = CloneXaml(cloneInputForAnimation);
            targetInput.Visibility = Visibility.Hidden;
            targetInput.Width = double.NaN;
            targetInput.Height = 50;
            nList.Children.Add(targetInput);

            //Obtaining the destination point
            Point targetPosition = targetInput.TransformToAncestor(rootView).Transform(new Point(0, 0));

            //Obtaining the current point
            Point currentPos = cloneInputForAnimation.TransformToAncestor(rootView).Transform(new Point(0, 0));

            //Calculating the translation to do to reach targetPosition
            Vector translateToDo = targetPosition - currentPos;

            TranslateTransform myTranslateTransform = new TranslateTransform();
            cloneInputForAnimation.RenderTransform = myTranslateTransform;

            DoubleAnimation myAnimX = new DoubleAnimation 
                Duration = animDuration,
                To = translateToDo.X
            ;

            DoubleAnimation myAnimY = new DoubleAnimation 
                Duration = animDuration,
                To = translateToDo.Y
            ;
            
            DoubleAnimation myAnimHeight = new DoubleAnimation 
                Duration = animDuration,
                To = 50,
            ;
            
            DoubleAnimation myAnimWidth = new DoubleAnimation 
                Duration = animDuration,
                To = 50,
            ;


            myTranslateTransform.BeginAnimation(TranslateTransform.YProperty, myAnimY);
            myTranslateTransform.BeginAnimation(TranslateTransform.XProperty, myAnimX);
            cloneInputForAnimation.BeginAnimation(TextBox.WidthProperty, myAnimWidth);
            cloneInputForAnimation.BeginAnimation(TextBox.HeightProperty, myAnimHeight);

C# CloneXaml 未被修改

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于动画化以编程方式创建的 xaml 对象的翻译的主要内容,如果未能解决你的问题,请参考以下文章

在 Unity 中以编程方式创建动画?

WPF XAML Trigger中使用动画后 动画对象冻结的处理办法

Win 10 应用开发UI Composition 札记:动画

以编程方式创建的动画 NSLayoutConstraint

Core Animation 文档翻译—附录B(可动画的属性)

如何在 XAML 中为 WinRT 中的贝塞尔路径设置动画