wpf 显示 UserControl 时会触发什么事件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4708039/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:30:43  来源:igfitidea点击:

What event is fired when a UserControl is displayed?

wpf

提问by Batibix

I'm trying to add a fade effect (animation) for WPF UserControls(although rather for FrameworkElement, to make it more general).

我正在尝试为 WPF 添加淡入淡出效果(动画)UserControls(尽管是为FrameworkElement,使其更通用)。

If I let the Loadedevent trigger the initial fade-in, the fade animation will sometimes have started before the UserControl has been displayed. The result is a mess. That happens for example if the UserControl does something lengthy (a few tenths of a second), like execute a query, in the Loaded event handler.

如果我让Loaded事件触发初始淡入,有时会在显示 UserControl 之前开始淡入淡出动画。结果一团糟。例如,如果 UserControl 在 Loaded 事件处理程序中执行一些冗长的操作(十分之几秒),例如执行查询,就会发生这种情况。

So, I would need to handle some event that FrameworkElement/UserControl gets when the content has been rendered, and start the fade-in then. The System.Windows.Windowhas a ContentRenderedevent, but UserControl has not. So, what event is fired when a FrameworkElement (or UserControl) has been rendered?

因此,我需要处理在呈现内容时 FrameworkElement/UserControl 获取的一些事件,然后开始淡入。该System.Windows.Window有一个ContentRendered事件,但是用户控件没有。那么,在呈现 FrameworkElement(或 UserControl)时会触发什么事件?

回答by Ievgen Naida

Try to check size on SizeChanged or LayoutUpdated. Do job when actual width or height not equals to 0.

尝试检查 SizeChanged 或 LayoutUpdated 上的大小。当实际宽度或高度不等于 0 时执行作业。

view.LayoutUpdated+=(o,e)=>
{
  if (!loaded && (view.ActualHeight > 0 || view.ActualWidth > 0))
  {
     // You can also unsubscribe event here.
     loaded =true;
  }
}

回答by Riva

Years late, but since I was looking for working solution since now in vain, I want to share my discovery.

晚了几年,但由于我一直在寻找有效的解决方案,因为现在徒劳无功,我想分享我的发现。

If you want a ContentRenderedevent for any Control (or any Visual or even DependencyObject), you have to dig down to Visual.

如果您想要ContentRendered任何 Control(或任何 Visual 甚至 DependencyObject)的事件,您必须深入到Visual.

I use this code:

我使用这个代码:

// 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;

    // ..
}

You have to wait for Control Loadedotherwise PresentationSource.FromVisual() returns null.

您必须等待 ControlLoaded否则 PresentationSource.FromVisual() 返回 null。

Various Dispatcher.BeginInvoke methods didn't work consistently for me. Sometimes firing my rendered event long before the control was actually displayed.
This does work for me every time.

各种 Dispatcher.BeginInvoke 方法对我来说并不一致。有时在控件实际显示之前很久就触发我的渲染事件。
这每次都对我有用。

I am aware that I am playing with HwndSource here, which is quite low level and I'm not sure of possible implications. (Maybe somebody more experienced can elaborate.)

我知道我在这里使用 HwndSource,这是相当低的级别,我不确定可能的影响。(也许更有经验的人可以详细说明。)

回答by Rick Sladkey

You can schedule the beginning of your Storyboardwith a lower priority, for example:

您可以Storyboard以较低的优先级安排开始,例如:

Dispatcher.BeginInvoke(BeginStoryboardAction, DispatcherPriority.ContextIdle);

Here's an article that discusses the issues related to using this method:

这是一篇讨论与使用此方法相关的问题的文章:

回答by H.B.

Maybe try IsVisibleChanged, haven't used it much myself though.

也许试试吧IsVisibleChanged,不过我自己没怎么用过。

This event is not raised if the element is not being rendered by the layout system, for reasons other than the value of the IsVisible property. For example, the element might not have an associated visual.

如果由于 IsVisible 属性值以外的原因,布局系统未呈现元素,则不会引发此事件。例如,元素可能没有关联的视觉对象。

回答by Mirza Bilal

You can use IsVisibleChnaged event Assign event handler

您可以使用 IsVisibleChnaged 事件分配事件处理程序

MyUserControl.IsVisibleChanged += ScheduleUserControl_IsVisibleChanged;

In event handler check for if is visible or not.

在事件处理程序中检查是否可见。

void _IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if ((bool)e.NewValue)
    {
        //Visible
    }
    else
    {
        //Not Visible
    }
}

回答by Mustafa Ekici

You can use GotFocus Event

您可以使用 GotFocus 事件

 <i:Interaction.Triggers>
        <i:EventTrigger EventName="GotFocus">
            <i:InvokeCommandAction Command="{Binding ContentControlLoadedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>