我正在尝试为WPF UserControls
添加淡入淡出效果(动画)(而不是FrameworkElement
,以使其更通用)。
如果我让Loaded
事件触发初始淡入,则淡入淡出动画有时会在UserControl显示之前启动。结果是一团糟。例如,如果UserControl在Loaded事件处理程序中执行冗长(十分之几秒),例如执行查询,则会发生这种情况。
因此,我需要处理一些在呈现内容时FrameworkElement / UserControl获取的事件,然后启动淡入。 System.Windows.Window
有ContentRendered
个事件,但UserControl没有。那么,在渲染FrameworkElement(或UserControl)时会触发什么事件?
答案 0 :(得分:19)
尝试在SizeChanged或LayoutUpdated上检查大小。当实际宽度或高度不等于0时执行。
view.LayoutUpdated+=(o,e)=>
{
if (!loaded && (view.ActualHeight > 0 || view.ActualWidth > 0))
{
// You can also unsubscribe event here.
loaded =true;
}
}
答案 1 :(得分:13)
已经很晚了,但是因为我现在一直在找工作解决方案,但是我想分享我的发现。
如果您想要任何Control(或任何Visual或甚至DependencyObject)的ContentRendered
事件,您必须深入研究Visual
。
我使用此代码:
// Wait for Control to Load
void TestUserControl_Loaded(object sender, RoutedEventArgs e)
{
// Get PresentationSource
PresentationSource presentationSource = PresentationSource.FromVisual((Visual)sender);
// Subscribe to PresentationSource's ContentRendered event
presentationSource.ContentRendered += TestUserControl_ContentRendered;
}
void TestUserControl_ContentRendered(object sender, EventArgs e)
{
// Don't forget to unsubscribe from the event
((PresentationSource)sender).ContentRendered -= TestUserControl_ContentRendered;
// ..
}
您必须等待Control Loaded
否则PresentationSource.FromVisual()将返回null。
各种Dispatcher.BeginInvoke方法对我来说并不一致。有时在实际显示控件之前很久就会触发渲染事件 这对我来说每次都有用。
我知道我在这里玩HwndSource,这是一个非常低的水平,我不确定可能的影响。 (也许更有经验的人可以详细说明。)
答案 2 :(得分:6)
也许尝试IsVisibleChanged
,但我自己并没有太多使用它。
如果元素未由布局系统呈现,则不会引发此事件,原因不是IsVisible属性的值。例如,元素可能没有关联的视觉效果。
答案 3 :(得分:6)
您可以安排优先级较低的Storyboard
的开头,例如:
Dispatcher.BeginInvoke(BeginStoryboardAction, DispatcherPriority.ContextIdle);
这篇文章讨论了与使用此方法相关的问题:
答案 4 :(得分:4)
您可以使用IsVisibleChnaged事件 分配事件处理程序
MyUserControl.IsVisibleChanged += ScheduleUserControl_IsVisibleChanged;
在事件处理程序中检查if是否可见。
void _IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
//Visible
}
else
{
//Not Visible
}
}
答案 5 :(得分:1)
您可以使用GotFocus事件
<i:Interaction.Triggers>
<i:EventTrigger EventName="GotFocus">
<i:InvokeCommandAction Command="{Binding ContentControlLoadedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>