当前位置: 动力学知识库 > 问答 > 编程问答 >

wpf - What event is fired when a UserControl is displayed?

问题描述:

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

If I let the Loaded event 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.

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.Window has a ContentRendered event, but UserControl has not. So, what event is fired when a FrameworkElement (or UserControl) has been rendered?

网友答案:

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

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

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

If you want a ContentRendered event for any Control (or any Visual or even DependencyObject), you have to dig down to 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 -= testContentRenderedUC_ContentRendered;

    // ..
}

You have to wait for Control Loaded otherwise PresentationSource.FromVisual() returns 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.

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.)

网友答案:

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

Dispatcher.BeginInvoke(BeginStoryboardAction, DispatcherPriority.ContextIdle);

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

  • Build More Responsive Apps With The Dispatcher
网友答案:

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

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.

网友答案:

You can use IsVisibleChnaged event Assign event handler

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
    }
}
分享给朋友:
您可能感兴趣的文章:
随机阅读: