我有一个自定义类,比如从wpf Canvas类派生的"MyCanvas"。MyCanvas有一个依赖属性"Scale",用于指定画布的比例变换。现在,当"比例"的值更改时,我想设置从旧值到新值的变换的动画。为此,我使用CCD_ 1方法。
代码:
//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);
XMAL:
<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')
如果有人对此有解决方案,请告诉我。感谢
这不是上述问题的解决方案,而是再现上述问题的工作样本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.
今天我在尝试一些事情,突然问题解决了。我不明白它是怎么开始工作的。我对代码进行了以下更改,我之前也尝试过。
scaleAnimation.FillBehavior = FillBehavior.Stop;
谁能向我解释一下吗?谢谢。
我可以证实我也遇到过这种情况,但我还没有找到一个干净的解决方案。我有一个案例,就像你在一个答案中描述的那样-关于滑块的更改在动画运行后不会影响绑定对象(是的,我将LayoutTransform.BeginAnimation(...)
0设置为Stop
和/或运行BeginAnimation(someProperty, null)
以"释放"动画对属性的"保持"。为了说明我仍然可以在动画后编辑属性(但不能使用作为绑定源的滑块),我设置了一个按钮,可以将属性设置为特定值。事实上,这个按钮在动画之后可以很好地更改该属性。在某些情况下,WPF的绑定可能会因为某些动画而中断。
一个不太干净的解决方法可能是在动画的Completed
处理程序中的代码中重新建立绑定。