2011-01-16 28 views
24

Estoy tratando de agregar un efecto de desvanecimiento (animación) para WPF UserControls (aunque más bien para FrameworkElement, para hacerlo más general).¿Qué evento se dispara cuando se muestra un UserControl?

Si dejo que el evento Loaded active el fundido de entrada inicial, la animación de fundido a veces habrá comenzado antes de que se muestre el UserControl. El resultado es un desastre. Eso sucede, por ejemplo, si el UserControl hace algo largo (algunas décimas de segundo), como ejecutar una consulta, en el controlador de eventos Loaded.

Por lo tanto, necesitaría manejar algún evento que FrameworkElement/UserControl obtenga cuando se haya procesado el contenido, y luego iniciar el fade-in. El System.Windows.Window tiene un evento ContentRendered, pero UserControl no. Entonces, ¿qué evento se dispara cuando se ha procesado FrameworkElement (o UserControl)?

Respuesta

5

Quizás intente IsVisibleChanged, aunque no lo he usado demasiado.

Este evento no se produce si el elemento no está siendo procesado por el sistema de diseño, por razones distintas al valor de la propiedad IsVisible. Por ejemplo, el elemento puede no tener un visual asociado.

+1

No, el elemento tiene IsVisible == true ya en el controlador de eventos Loaded. – Batibix

+0

Lástima, ¿qué hay de desencadenar su fundido manualmente cuando se completa su trabajo inicial? –

+1

El problema es: ¿dónde debo activarlo? Después de que se maneja el evento Loaded, algo largo todavía tiene lugar. Probablemente sea un enlace de datos de WPF que active la carga de Entity Framework desde la base de datos en algún lugar entre el evento Loaded y la visualización del UserControl. – Batibix

6

Puede programar el comienzo de su Storyboard con una prioridad más baja, por ejemplo:

Dispatcher.BeginInvoke(BeginStoryboardAction, DispatcherPriority.ContextIdle); 

He aquí un artículo que trata sobre las cuestiones relacionadas con el uso de este método:

18

Intente verificar el tamaño en SizeChanged o LayoutUpdated. Qué trabajo cuando la anchura o la altura real no es igual a 0.

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

Gracias! Muy útil para mis preguntas http://stackoverflow.com/q/18724686/352101 – Bolu

4

Puede utilizar IsVisibleChnaged caso controlador de eventos Asignar

MyUserControl.IsVisibleChanged += ScheduleUserControl_IsVisibleChanged; 

En comprobación de controlador de eventos para, si es visible o no.

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

H.B. Ya lo escribí en su respuesta. –

+1

.. y por qué no funciona. – Riva

10

Atrasados, pero como estaba buscando una solución de trabajo desde ahora en vano, quiero compartir mi descubrimiento.

Si desea un evento ContentRendered para cualquier Control (o cualquier Visual o incluso DependencyObject), tiene que buscar Visual.

utilizo este código:

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

    // .. 
} 

Tienes que esperar para el Control de Loaded lo contrario PresentationSource.FromVisual() devuelve un valor nulo.

Varios métodos Dispatcher.BeginInvoke no funcionaron consistentemente para mí. A veces disparando mi evento renderizado mucho antes de que realmente se mostrara el control.
Esto funciona para mí todo el tiempo.

Soy consciente de que estoy jugando con HwndSource aquí, que es bastante bajo nivel y no estoy seguro de posibles implicaciones. (Tal vez alguien con más experiencia puede dar más detalles.)

+3

Desafortunadamente, 'ContentRendered' se activa solo la primera vez que el propietario' Window' finaliza la representación; eso significa: si este 'UserControl' (o cualquier' DependencyObject') se representa ** después de que ** 'ContentRendered' se active, no se volverá a disparar. Este problema puede ser contrarrestado cuando tiene algunos controles que se cargan de forma lenta dependiendo de la interacción del usuario. –

1

Usted puede utilizar Evento GotFocus

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