如何在从可视化树中删除元素之前执行一些代码



我正在尝试为WPF中的用户控件实现一些淡入淡出动画。对于淡入动画,我可以使用Loaded事件来实现这一点。

public sealed partial class NowPlayingView : UserControl
{
public Duration AnimationDuration
{
get { return (Duration)GetValue(AnimationDurationProperty); }
set { SetValue(AnimationDurationProperty, value); }
}
public static readonly DependencyProperty AnimationDurationProperty =
DependencyProperty.Register("AnimationDuration", typeof(Duration), typeof(NowPlayingView), new PropertyMetadata(Duration.Automatic));
public NowPlayingView()
{
Opacity = 0;
InitializeComponent();
Loaded += NowPlayingView_Loaded;
Unloaded += NowPlayingView_Unloaded;
}
private void NowPlayingView_Unloaded(object sender, RoutedEventArgs e)
{
DoubleAnimation animation = new(1.0, 0.0, AnimationDuration);
BeginAnimation(OpacityProperty, animation);
}
private void NowPlayingView_Loaded(object sender, RoutedEventArgs e)
{
DoubleAnimation animation = new (0.0, 1.0, AnimationDuration);
BeginAnimation(OpacityProperty, animation);
}
}

我尝试将Unloaded事件用于淡出效果,结果发现该事件是在从视觉树中删除UserControl之后(当UserControl不再可见或可访问时(触发的。有没有一种方法可以在UserControl"之前运行一些代码;关闭";,类似于WindowOnClosing事件?

编辑:

对于更多的上下文,UserControl充当更复杂窗口的组件。每当属性NowPlayingViewModel不为null时,它就会被激活,而当为null时它就会被停用(我这样做是为了隐藏UserControl(。当我将ViewModel设置为null时,我希望运行淡出动画,并且希望保持代码与其他ViewModel逻辑解耦。

<!-- Now playing View-->
<ContentControl Grid.RowSpan="3" Grid.ColumnSpan="2" Content="{Binding NowPlayingViewModel}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type viewmodels:NowPlayingViewModel}">
<views:NowPlayingView AnimationDuration="00:00:00.8" />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>

从我的测试来看,到目前为止,我还没有找到任何好的解决方案,尽管我对导致类似行为的建议持开放态度。

我找到了一个更简单、更优雅的解决方案。

public sealed partial class NowPlayingView : UserControl
{
private bool _animating = false;
public bool ShowWindow
{
get { return (bool)GetValue(ShowWindowProperty); }
set { SetValue(ShowWindowProperty, value); }
}
public static readonly DependencyProperty ShowWindowProperty =
DependencyProperty.Register("ShowWindow", typeof(bool), typeof(NowPlayingView), new PropertyMetadata(false, OnShowWindowChanged));
private static void OnShowWindowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is NowPlayingView userControl && (bool)e.NewValue == true)
userControl.Show();            
}
public NowPlayingView()
{
InitializeComponent();
Opacity = 0;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
_animating = true;
Hide();
_animating = false;
}
private void Show()
{
Visibility = Visibility.Visible;
DoubleAnimation animation = new()
{
From = 0.0,
To = 1.0,
FillBehavior = FillBehavior.HoldEnd,
Duration = new(TimeSpan.FromMilliseconds(600))
};
Storyboard storyboard = new();
storyboard.Children.Add(animation);
Storyboard.SetTarget(animation, this);
Storyboard.SetTargetProperty(animation, new PropertyPath(OpacityProperty));
storyboard.Begin();
}
private void Hide()
{
DoubleAnimation animation = new()
{
From = 1.0,
To = 0.0,
FillBehavior = FillBehavior.Stop,
Duration = new(TimeSpan.FromMilliseconds(600))
};
Storyboard storyboard = new();
storyboard.Children.Add(animation);
Storyboard.SetTarget(animation, this);
Storyboard.SetTargetProperty(animation, new PropertyPath(OpacityProperty));
storyboard.Completed += delegate 
{ 
Visibility = Visibility.Collapsed; 
};
storyboard.Begin();
}
}

我创建了一个依赖属性ShowWindow。每当属性更改为true时,都会触发淡入动画的情节提要。对于淡出,我只是挂起了一个按钮OnClick事件,但我可以在DependencyPropertyChanged方法中轻松地做到这一点。

通过这种方式,我在一定程度上保持代码解耦,并使用绑定到UserControl上的ShowWindow依赖属性的属性直接从其ViewModel控制UserControl的动画。

最新更新