1

我有一个自定义类,说从 wpf Canvas 类派生的“MyCanvas”。MyCanvas 有一个依赖属性“Scale”,它指定画布的比例变换。现在,当 Scale 的值发生变化时,我想为从旧值到新值的转换设置动画。为此,我正在使用LayoutTransform.BeginAnimation(...)方法。

代码:

//This represents the time it will take to zoom
Duration zoomDuration = new Duration(TimeSpan.Parse("0:0:0.3"));

//Set up animation for zooming
DoubleAnimationUsingKeyFrames scaleAnimation = new DoubleAnimationUsingKeyFrames();
scaleAnimation.Duration = zoomDuration;
scaleAnimation.KeyFrames = GetAnimationSplines(newScale);
scaleAnimation.Completed += new EventHandler(
    (sender, e) => Scale = newScale);

// Start the scale (zoom) animations
LayoutTransform.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
LayoutTransform.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation);

圣诞节:

<Grid>
    <ItemsControl x:Name="Items">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <local:MyCanvas Scale="{Binding Scale, Mode=TwoWay}">
                    <local:MyCanvas.LayoutTransform UseLayoutRounding="True">
                        <ScaleTransform ScaleX="{Binding Scale, Mode=TwoWay}" 
                                        ScaleY="{Binding Scale, Mode=TwoWay}"/>
                    </local:MyCanvas.LayoutTransform>
                 </local:MyCanvas>
             </ItemsPanelTemplate>
         </ItemsControl.ItemsPanel>
    </ItemsControl>
</Grid>

但是在执行此代码后,与(视图模型中的一个属性)的绑定ScaleX正在ScaleY中断Scale,即更改的值Scale不会改变画布上的比例。

错误消息(使用 Snoop):

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Scale; DataItem=null; target element is 'ScaleTransform' (HashCode=796423); target property is 'ScaleX' (type 'Double')

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Scale; DataItem=null; target element is 'ScaleTransform' (HashCode=796423); target property is 'ScaleY' (type 'Double')

请让我知道是否有人对此有解决方案。谢谢

4

3 回答 3

0

这不是上述问题的解决方案,而是WPF Application重现上述问题的工作示例。

XAML:

<Window x:Class="TestWpfApplication.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="auto" />
    </Grid.RowDefinitions>

    <Grid Grid.Row="0">
        <Grid.LayoutTransform>
            <ScaleTransform ScaleX="{Binding ElementName=zoomer, Path=Value}" ScaleY="{Binding ElementName=zoomer, Path=Value}" x:Name="scaleTx" />
        </Grid.LayoutTransform>

        <Border Background="Aqua" BorderThickness="3" BorderBrush="Blue" Height="50" Width="50" />
    </Grid>
    <StackPanel Orientation="Horizontal" Grid.Row="1">
        <Slider x:Name="zoomer" Width="200" Value="1" Minimum="0.1" Maximum="3" TickFrequency="0.1" IsSnapToTickEnabled="True" Margin="3"/>
        <Button Content="Animate" Click="Button_Click" Margin="3"/>
    </StackPanel>
</Grid>

代码:

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {

        //This represents the time it will take to zoom
        Duration zoomDuration = new Duration(TimeSpan.Parse("0:0:0.5"));

        //Set up animation for zooming
        DoubleAnimationUsingKeyFrames scaleAnimation = new DoubleAnimationUsingKeyFrames();
        scaleAnimation.Duration = zoomDuration;
        scaleAnimation.KeyFrames = GetAnimationSplines(zoomer.Maximum);

        scaleTx.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
        scaleTx.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation);
    }

    /// <summary>
    /// This creates a spline for zooming with non-linear acceleration patterns.
    /// </summary>
    /// <param name="moveTo"></param>
    /// <returns></returns>
    protected DoubleKeyFrameCollection GetAnimationSplines(double moveTo)
    {
        DoubleKeyFrameCollection returnCollection = new DoubleKeyFrameCollection();

        returnCollection.Add(new LinearDoubleKeyFrame(moveTo, KeyTime.FromPercent(1.0)));

        return returnCollection;
    }
}

The shape in the center of window will scale when slide is moved. Once you click animate button to apply animation, the zooming will animate but after that slider stops working.

于 2012-03-27T11:08:39.990 回答
0

好吧,今天我正在尝试一些事情,突然问题得到了解决。我不明白它是如何开始工作的。我对代码进行了以下更改,我之前也尝试过。

scaleAnimation.FillBehavior = FillBehavior.Stop;

谁能给我解释一下。谢谢。

于 2012-03-29T04:36:43.260 回答
0

我可以证实我也发生过这种情况,但我还没有找到一个干净的解决方案。我有一个案例,就像您在一个答案中描述的那样 - 关于在动画运行后滑块更改不会影响绑定对象(是的,我FillBehavior设置Stop和/或运行BeginAnimation(someProperty, null)以“释放”动画的“保持”在属性上。为了说明我仍然可以在动画后编辑属性(但不能使用作为绑定源的滑块),我设置了一个按钮,将属性设置为特定值。这个按钮确实有效完美地在动画之后更改该属性。似乎在某些情况下,WPF 的绑定可能会因某些动画而中断。

Completed一个不太干净的解决方法可能是在动画处理程序 的代码中重新建立绑定。

于 2013-03-08T16:57:34.070 回答