Анимация LayoutTransform на ScaleX и ScaleY нарушает связывание с ними - PullRequest
1 голос
/ 26 марта 2012

У меня есть собственный класс, скажем, «MyCanvas», полученный из класса wpf Canvas.MyCanvas имеет свойство зависимости «Масштаб», которое задает преобразование масштаба для холста.Теперь, когда значение 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);

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 (свойство в viewmodel) разрывается, т.е. изменение значения 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')

Пожалуйста, дайте мне знать, если у кого-то есть решение для этого.Спасибо

Ответы [ 3 ]

0 голосов
/ 29 марта 2012

Ну, сегодня я попробовал кое-что, и внезапно проблема была решена.Я не понял, как это начинает работать.Я сделал следующие изменения в коде, который я пробовал ранее.

scaleAnimation.FillBehavior = FillBehavior.Stop;

Может кто-нибудь объяснить это мне.Спасибо.

0 голосов
/ 08 марта 2013

Я могу подтвердить, что у меня тоже было такое, но я еще не нашел чистого решения.У меня был случай, как вы описали в одном из ваших ответов - касательно изменения ползунка, не затрагивающего привязанный объект после запуска анимации (и да, у меня FillBehavior установлено значение Stop и / или выполняется BeginAnimation(someProperty, null)чтобы «отпустить» анимацию, «удерживающую» свойство. Чтобы проиллюстрировать, что я все еще могу редактировать свойство после анимации (но не с помощью ползунка, который был источником привязки), я установил кнопку, которая установит для свойства значениеконкретное значение. Эта кнопка действительно отлично работала, чтобы изменить это свойство после анимации. Похоже, что в некоторых случаях привязка WPF может прерваться из-за определенных анимаций.

Не очень чистый обходной путь может бытьвосстановить привязку в коде в обработчике Completed анимации.

0 голосов
/ 27 марта 2012

Это не решение вышеуказанной проблемы, а рабочий образец 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.

...