2017-10-20 2 views
0

Ich versuche, ein Benutzersteuerelement zu erstellen, das die Größe ändern und (mit einer Animation) reduzieren/erweitern kann. Die Größenanpassung funktioniert nicht mehr, wenn ich die Minimierungs-/Maximierungsanimation spiele. AppWPF-Problem mit einem resizable/reduzierbaren Benutzersteuerelement

EDIT:

komplette Testanwendung finden Sie hier hier ist der entsprechende Code als

MyControl.xaml angefordert:

<UserControl x:Class="WpfApp1.MyControl" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:local="clr-namespace:WpfApp1" 
     mc:Ignorable="d" 
     d:DesignHeight="300" 
     d:DesignWidth="300"> 

<Grid Background="#FF935E5E"> 
    <Thumb Width="8" 
      HorizontalAlignment="Right" 
      Margin="0,0,-4,0" 
      DragDelta="Thumb_DragDelta" 
      Cursor="SizeWE"/> 
</Grid> 

MyContr ol.xaml.cs:

using System; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media.Animation; 

namespace WpfApp1 
{ 
    /// <summary> 
    /// Interaction logic for MyControl.xaml 
    /// </summary> 
    public partial class MyControl : UserControl 
    { 

     public bool IsOpen 
     { 
      get { return (bool)GetValue(IsOpenProperty); } 
      set { SetValue(IsOpenProperty, value); } 
     } 
     public static readonly DependencyProperty IsOpenProperty = 
      DependencyProperty.Register("IsOpen", typeof(bool), typeof(MyControl), new PropertyMetadata(true, OnIsOpenChanged)); 

     private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      MyControl control = d as MyControl; 
      control.PlayAnimation(); 
     } 



     public double OpenWidth 
     { 
      get { return (double)GetValue(OpenWidthProperty); } 
      set { SetValue(OpenWidthProperty, value); } 
     } 
     public static readonly DependencyProperty OpenWidthProperty = 
      DependencyProperty.Register("OpenWidth", typeof(double), typeof(MyControl), new PropertyMetadata(300d, OnOpenWidthChanged)); 

     private static void OnOpenWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      MyControl control = d as MyControl; 
      if (control.IsOpen) 
       control.Width = control.OpenWidth; 
     } 



     public MyControl() 
     { 
      InitializeComponent(); 
      if (IsOpen) 
       Width = OpenWidth; 
     } 

     private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) 
     { 
      OpenWidth += e.HorizontalChange; 
     } 


     private void PlayAnimation() 
     { 
      DoubleAnimation sizeAnimation = new DoubleAnimation(IsOpen ? OpenWidth : 0, TimeSpan.FromMilliseconds(250)); 
      sizeAnimation.EasingFunction = new CircleEase() { EasingMode = EasingMode.EaseInOut }; 
      BeginAnimation(WidthProperty, sizeAnimation); 

     } 
    } 
} 

MainWindow.xaml:

<Window x:Class="WpfApp1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:WpfApp1" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="700"> 

<DockPanel> 
    <local:MyControl IsOpen="{Binding ControlIsOpen}" 
        OpenWidth="{Binding ControlOpenWidth}"/> 
    <Grid Background="Green"> 
     <Button Width="100" 
       Height="20" 
       Content="Test Animation" 
       Click="Button_Click"/> 
    </Grid> 
</DockPanel> 

MainWindow.xaml.cs:

using System.ComponentModel; 
using System.Runtime.CompilerServices; 
using System.Windows; 

namespace WpfApp1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     #region INotifyPropertyChanged 

     public event PropertyChangedEventHandler PropertyChanged; 
     protected void OnPropertyChanged([CallerMemberName] string propertyName = null) => 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 

     #endregion INotifyPropertyChanged 


     private bool _ControlIsOpen = true; 
     public bool ControlIsOpen 
     { 
      get => _ControlIsOpen; 
      set 
      { 
       _ControlIsOpen = value; 
       OnPropertyChanged(); 
      } 
     } 


     private double _ControlOpenWidth = 300d; 
     public double ControlOpenWidth 
     { 
      get => _ControlOpenWidth; 
      set 
      { 
       _ControlOpenWidth = value; 
       OnPropertyChanged(); 
      } 
     } 



     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = this; 
     } 


     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      ControlIsOpen = !ControlIsOpen; 
     } 
    } 
} 

Danke für die Hilfe :)

+0

Sie sollten die Schlüsselcodes hier einfügen, damit andere das Problem schnell bekommen. Das kann auch denen helfen, die die gleichen Probleme haben. – Iron

+0

Haben Sie Storyboard verwendet? Es gibt eine Fill-Eigenschaft, die auf Halten von Stopp gesetzt werden kann. Wenn Sie das Standard-Hold-Verhalten beibehalten, wird DependencyProperty vom Storyboard aktualisiert, selbst wenn der Endwert erreicht ist. – Dmitry

+0

Sie beabsichtigen, die Eigenschaft zu ändern, nachdem das Storyboard fertiggestellt wurde? – Iron

Antwort

1

Die Animation hört eigentlich nie auf Sie sollten FillBehavior to Stop angeben. In diesem Fall stoppt die Annimierung die Aktualisierung der Eigenschaft, nachdem der endgültige Wert erreicht wurde.

private void PlayAnimation() 
    { 
     DoubleAnimation sizeAnimation = new DoubleAnimation(IsOpen ? OpenWidth : 0, TimeSpan.FromMilliseconds(250)); 
     sizeAnimation.FillBehavior = FillBehavior.Stop; 
     sizeAnimation.EasingFunction = new CircleEase() { EasingMode = EasingMode.EaseInOut }; 
     sizeAnimation.Completed += OnAnimationCompleted; 
     BeginAnimation(WidthProperty, sizeAnimation); 

    } 

    private void OnAnimationCompleted(object sender, EventArgs e) 
    { 
     Width = IsOpen ? OpenWidth : 0; 
    } 

Der Standardwert ist HoldEnd. Und das Storyboard ändert die Breite, bis es nicht explizit gestoppt wird.

https://msdn.microsoft.com/en-us/library/system.windows.media.animation.timeline.fillbehavior(v=vs.110).aspx

Einige weitere Informationen https://docs.microsoft.com/en-us/dotnet/framework/wpf/graphics-multimedia/how-to-set-a-property-after-animating-it-with-a-storyboard

+0

Ich ging mit der gleichen Lösung :) Wusste nicht über die FillBehavior obwohl, also danke für dieses :) – Sugz

0

Nun dank Dmitry Idee, ich habe in der Lage, es zu lösen, indem Sie das Füllverhalten Einstellung zu stoppen und zwingt zu Breite entweder 0 oder offen zu sein Breite:

private void PlayAnimation() 
{ 
    DoubleAnimation sizeAnimation = new DoubleAnimation(IsOpen ? OpenWidth : 0, TimeSpan.FromMilliseconds(250)); 
    sizeAnimation.EasingFunction = new CircleEase() { EasingMode = EasingMode.EaseInOut }; 
    sizeAnimation.FillBehavior = FillBehavior.Stop; 
    sizeAnimation.Completed += (s, e) => Width = (IsOpen ? OpenWidth : 0); 
    BeginAnimation(WidthProperty, sizeAnimation); 

} 

Dank all :)

Verwandte Themen