1

У меня есть пользовательский класс, который говорит «MyCanvas», полученный из класса Canvas класса wpf. В MyCanvas есть свойство «Масштаб» зависимости, которое определяет масштабное преобразование для холста. Теперь, когда изменяется значение Scale, я хочу оживить преобразование от старого значения до нового значения. для этого я использую метод LayoutTransform.BeginAnimation(...).LayoutTransform анимация на ScaleX и ScaleY нарушает привязку с ними

Код:

//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')

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

+0

Где вы привязывали свойство ScaleTransform к свойству LayoutTransform? Пожалуйста, покажите этот код. Или не так ли? – Clemens

ответ

0

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

scaleAnimation.FillBehavior = FillBehavior.Stop; 

Может кто-нибудь объяснить это мне. Благодарю.

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.

0

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

Обходное решение, не столь чистая, может заключаться в восстановлении привязки кода в обработчике Completed анимации.