Создание анимации слайдов в wpf - PullRequest
0 голосов
/ 02 июня 2018

У меня есть сетка, которая используется в качестве контейнера.Сетка состоит из UserControl, каждый из которых имеет высоту 600 пикселей и ширину 800 пикселей.Я хочу сделать анимацию слайдов похожей на презентацию, переключая видимые элементы управления.Вот мой xaml-код mainWindow:

<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, но он дает значение, котороебольше моего разрешения экрана.Так что часть моего контроля уходит за экран.И после завершения анимации она возвращается обратно.Использование любого свойства width сетки дает неправильное значение, даже с UpdateLayout () для события resize.

Редактировать: Снимки экрана

После завершения анимации ипосле _container.HorizontalAlignment = HorizontalAlignment.Stretch;.

1 Ответ

0 голосов
/ 03 июня 2018

Вы пытаетесь анимировать ширину или высоту определенного элемента интерфейса?Вам нужно создать собственный класс анимации, который расширяет AnimationTimeline и определить анимацию внутри Storyboard в XAML.Вам нужно будет создать собственный класс 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);
            }
        }
    }
}

. Затем вы можете использовать это в XAML внутри Storyboard, например:

<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>

StartAnimationWidth и EndAnimationWidth являются свойствами типа GridLength и определены в 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...