带有mvvm模式的Wpf动画

时间:2013-10-03 09:17:05

标签: wpf animation mvvm

关于动画的小例子,在动画

中不起作用的模型属性的变化
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="440" Width="732" Loaded="Window_Loaded"
    MouseLeftButtonDown="Grid_MouseLeftButtonDown" MouseLeftButtonUp="Grid_MouseLeftButtonUp" MouseMove="Grid_MouseMove">
<Window.Resources>

</Window.Resources>
<Grid>        
    <Grid.RowDefinitions>
        <RowDefinition Height="20"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
        <RowDefinition Height="20"></RowDefinition>
    </Grid.RowDefinitions>        
    <Canvas Name="canvMain" Height="360" Width="710" Grid.Row="1">
        <Rectangle Name="Zombi" Width="20" Height="40" Stroke="Black" StrokeThickness="2" Canvas.Bottom="0" Canvas.Right="{Binding Path=X, UpdateSourceTrigger=PropertyChanged, NotifyOnTargetUpdated=True}"></Rectangle>
    </Canvas>
</Grid>

public double X
    {
        get { return _x; }
        set
        {
            if (!double.IsNaN(value))
            {
                _x = value;
                OnPropertyChanged("X");
            }
        }
    }

double pixelMetr = 0.715;

    private int GetPixel(double metr)
    {
        return Convert.ToInt32(metr / pixelMetr);
    }

private void StartZombi()
    {
        double distance = 250;
        double maxTime = (new Random()).Next(5, 10);

        PathGeometry animationPath = new PathGeometry();

        LineGeometry lineGeometry = new LineGeometry();
        lineGeometry.StartPoint = new Point(0, 0);
        lineGeometry.EndPoint = new Point(GetPixel(distance), 0);

        animationPath.AddGeometry(lineGeometry);

        DoubleAnimationUsingPath animationX = new DoubleAnimationUsingPath();
        animationX.PathGeometry = animationPath;
        animationX.Duration = TimeSpan.FromSeconds(maxTime);
        animationX.Source = PathAnimationSource.X;
        Storyboard.SetTarget(animationX, Zombi);
        Storyboard.SetTargetProperty(animationX, new PropertyPath(Canvas.RightProperty));

        Storyboard pathAnimationStoryboard = new Storyboard();
        pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever;
        pathAnimationStoryboard.Children.Add(animationX);

        pathAnimationStoryboard.Begin(this);
    }

你好为什么不能更改属性,我需要在动画运行时获取属性'canvas.right'的当前值。

这是xaml代码。

1 个答案:

答案 0 :(得分:0)

好的,我找到了解决方案......您只需为DependencyProperty创建一个X并为其设置动画:

public static readonly DependencyProperty XProperty = DependencyProperty.
    Register("X", typeof(double), typeof(MainWindow));

public double X
{
    get { return (double)GetValue(XProperty); }
    set { SetValue(XProperty, value); }
}

然后你的动画方法:

private void StartZombi()
{
    double distance = 250;
    double maxTime = (new Random()).Next(5, 10);

    PathGeometry animationPath = new PathGeometry();

    LineGeometry lineGeometry = new LineGeometry();
    lineGeometry.StartPoint = new Point(0, 0);
    lineGeometry.EndPoint = new Point(GetPixel(distance), 0);

    animationPath.AddGeometry(lineGeometry);

    DoubleAnimationUsingPath animationX = new DoubleAnimationUsingPath();
    animationX.PathGeometry = animationPath;
    animationX.Duration = TimeSpan.FromSeconds(maxTime);
    animationX.Source = PathAnimationSource.X;
    Storyboard.SetTarget(animationX, This); // <<< 'This' is the Window.Name
    Storyboard.SetTargetProperty(animationX, 
        new PropertyPath(MainWindow.XProperty));

    Storyboard pathAnimationStoryboard = new Storyboard();
    pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever;
    pathAnimationStoryboard.Children.Add(animationX);

    pathAnimationStoryboard.Begin(this);
}

和XAML:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>
    <Canvas Name="canvMain" Height="360" Width="710" Grid.Row="1">
        <Rectangle Name="Zombi" Width="20" Height="40" Stroke="Black" 
            StrokeThickness="2" Canvas.Bottom="60" Canvas.Right="{Binding Path=X,
            UpdateSourceTrigger=PropertyChanged}" />
    </Canvas>
    <TextBlock Grid.Row="0" FontSize="26" Text="{Binding X}" />
</Grid>

要完成这项工作,您需要做的最后一件事是将Window.Name属性设置为"This"

为了回答原始问题,为什么你的代码不起作用,我不是百分百肯定,但我认为这是因为Canvas.X属性没有插入INotifyPropertyChanged接口所以你的原始CLR X属性设置器从未被调用过。当Binding到集合的Count属性时会出现类似的情况......当您向集合添加项目时,它不会更新UI,因为它没有通知更改。