我有一个用作容器的网格。网格由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,但它提供的值超过了我的显示分辨率。所以我控制的一部分就在屏幕后面。动画完成后返回。使用网格的任何width属性都会给出错误的值,即使在resize事件上使用UpdateLayout()也是如此。
修改 Screenshots
动画完成后和_container.HorizontalAlignment = HorizontalAlignment.Stretch;
之后。
答案 0 :(得分:0)
您是否尝试为某个UI元素的宽度或高度设置动画?您需要创建一个扩展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();