繁体   English   中英

在wpf中制作幻灯片动画

[英]Making slide animation in wpf

我有一个网格,用作容器。 网格由UserControl组成,每个网格的高度为600px,宽度为800px。 我想通过切换可视控件来制作幻灯片动画,就像演示一样。 这是我的mainWindow的xaml代码:

<Window x:Class="MessengerWindowsClient.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:MessengerWindowsClient"
    xmlns:pages="clr-namespace:MessengerWindowsClient.Pages"
    mc:Ignorable="d"
    Title="MainWindow" Height="600" Width="800" Closed="Window_Closed">
<Window.Background>
    <ImageBrush ImageSource="Resources/background.jpg"></ImageBrush>
</Window.Background>
<Grid x:Name="Container" RenderTransformOrigin="0.5,0.5" SizeChanged="Container_SizeChanged">
    <pages:WelcomePage x:Name ="WelcomePage" Visibility="Visible" RegisterPage="{Binding ElementName=RegisterPage}" LoginPage="{Binding ElementName=LoginPage}"/>
    <pages:MessagesPage Visibility="Collapsed"/>
    <pages:LoginPage x:Name="LoginPage" Visibility="Collapsed" WelcomePage="{Binding ElementName=WelcomePage}"/>
    <pages:RegisterPage x:Name="RegisterPage" Visibility="Collapsed" WelcomePage="{Binding ElementName=WelcomePage}"/>
</Grid>

这是代码背后:

public partial class MainWindow : Window
{
    private ServiceManager _serviceManager;
    private UIElement _currentPage;

    public MainWindow()
    {
        InitializeComponent();
        _currentPage = this.Container.Children[0];
        this.RegisterPage.RegisterReady += RegisterUser;
        this.RegisterPage.ChangePage += ChangePage;
        this.WelcomePage.ChangePage += ChangePage;
        this.LoginPage.ChangePage += ChangePage;
        _serviceManager = new ServiceManager();
    }

    private void ChangePage(object sender, ChangePageEventArgs e)
    {
        switch (e.Direction)
        {
            case ChangePageDirection.Forward:
                AnimationManager.AnimateForwardPage(e.NewPage, e.OldPage, Container, this.ActualWidth);
                break;
            case ChangePageDirection.Backward:
                AnimationManager.AnimateBackwardPage(e.NewPage, e.OldPage, Container, this.ActualWidth);
                break;
        }
    }

    private async void RegisterUser(object sender, RegisterEventArgs e)
    {
        var isSucceed = await _serviceManager.RegisterUser(e.Name, e.Username, e.Password.ToString(), e.Email);
        e.Password.Dispose();
    }

    private void Window_Closed(object sender, EventArgs e)
    {
        _serviceManager.Dispose();
    }

    private void Container_SizeChanged(object sender, SizeChangedEventArgs e)
    {

            UpdateLayout();
        }
    }
}

我尝试使用this.ActualWidth,但它提供的值超过了我的显示分辨率。 所以我控制的一部分就在屏幕后面。 动画完成后返回。 即使对resize事件使用UpdateLayout(),使用网格的任何width属性都会给出错误的值。

编辑: 截图

动画完成后_container.HorizontalAlignment = HorizontalAlignment.Stretch;

您是否尝试为某个UI元素的宽度或高度设置动画? 您需要创建一个自定义动画类,该类扩展AnimationTimeline并在XAMLStoryboard中定义动画。 您需要创建一个自定义类GridLengthAnimation

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Animation;

namespace Infrastructure.Animations
{
    public class GridLengthAnimation : AnimationTimeline
    {
        protected override Freezable CreateInstanceCore()
        {
            return new GridLengthAnimation();
        }

        public override Type TargetPropertyType => typeof(GridLength);

        static GridLengthAnimation()
        {
            FromProperty = DependencyProperty.Register("From", typeof(GridLength),
                typeof(GridLengthAnimation));

            ToProperty = DependencyProperty.Register("To", typeof(GridLength),
                typeof(GridLengthAnimation));
        }

        public static readonly DependencyProperty FromProperty;
        public GridLength From
        {
            get => (GridLength)GetValue(GridLengthAnimation.FromProperty);
            set => SetValue(GridLengthAnimation.FromProperty, value);
        }

        public static readonly DependencyProperty ToProperty;
        public GridLength To
        {
            get => (GridLength)GetValue(GridLengthAnimation.ToProperty);
            set => SetValue(GridLengthAnimation.ToProperty, value);
        }

        public override object GetCurrentValue(object defaultOriginValue,
    object defaultDestinationValue, AnimationClock animationClock)
        {
            double fromVal = ((GridLength)GetValue(GridLengthAnimation.FromProperty)).Value;
            double toVal = ((GridLength)GetValue(GridLengthAnimation.ToProperty)).Value;
            if (fromVal > toVal)
            {
                return new GridLength((1 - animationClock.CurrentProgress.Value) *
                    (fromVal - toVal) + toVal, GridUnitType.Pixel);
            }
            else
            {
                return new GridLength(animationClock.CurrentProgress.Value *
                    (toVal - fromVal) + fromVal, GridUnitType.Pixel);
            }
        }
    }
}

然后,你可以在Storyboard中的XAML使用它,如下所示:

<Storyboard x:Key="storyboardName">
            <support:GridLengthAnimation Storyboard.TargetName="YourElementToAnimate" Storyboard.TargetProperty="Width" From="{Binding StartAnimationWidth}" To="{Binding EndAnimationWidth}" DecelerationRatio="0.9" Duration="0:0:0.6"/>            
</Storyboard>

StartAnimationWidthEndAnimationWidthGridLength类型的属性,在ViewModel中定义

private GridLength _endAnimationWidth = new GridLength(100);
public GridLength EndAnimationWidth
{
    get => _endAnimationWidth;
    set => SetProperty(ref _endAnimationWidth,value);
}

然后,您可以从后面的代码触发动画:

Storyboard sb = Resources["storyboardName"] as Storyboard;
sb.Begin();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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