Какое событие вызывается при отображении UserControl? - PullRequest
29 голосов
/ 17 января 2011

Я пытаюсь добавить эффект затухания (анимацию) для WPF UserControls (хотя, скорее, для FrameworkElement, чтобы сделать его более общим).

Если я позволю событию Loaded инициировать начальное постепенное появление, анимация постепенного изменения иногда запускается до отображения UserControl. Результатом является беспорядок. Это происходит, например, если UserControl выполняет что-то длительное (несколько десятых секунды), например, выполняет запрос в обработчике событий Loaded.

Итак, мне нужно обработать какое-то событие, которое FrameworkElement / UserControl получает при рендеринге контента, и затем начать постепенное появление. System.Windows.Window имеет событие ContentRendered, а UserControl - нет. Итак, какое событие вызывается при визуализации FrameworkElement (или UserControl)?

Ответы [ 6 ]

19 голосов
/ 02 сентября 2013

Попробуйте проверить размер на SizeChanged или LayoutUpdated.Выполняйте работу, когда фактическая ширина или высота не равна 0.

view.LayoutUpdated+=(o,e)=>
{
  if (!loaded && (view.ActualHeight > 0 || view.ActualWidth > 0))
  {
     // You can also unsubscribe event here.
     loaded =true;
  }
}
13 голосов
/ 29 июня 2015

Спустя годы, но так как я искал рабочее решение, так как теперь напрасно, я хочу поделиться своим открытием.

Если вы хотите событие ContentRendered для любого элемента управления (или любого визуального или даже DependencyObject)), вы должны копать до 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 () возвращает ноль.

Различные методы Dispatcher.BeginInvoke не работали для меня согласованно.Иногда запускаю мое визуализированное событие задолго до того, как элемент управления фактически отобразился.
Это работает для меня каждый раз.

Мне известно, что я играю здесь с HwndSource, который является довольно низким уровнем, и я не уверен в возможных последствиях.(Может быть, кто-то более опытный может уточнить.)

6 голосов
/ 17 января 2011

Вы можете запланировать начало вашего Storyboard с более низким приоритетом, например:

Dispatcher.BeginInvoke(BeginStoryboardAction, DispatcherPriority.ContextIdle);

Вот статья, в которой обсуждаются вопросы, связанные с использованием этого метода:

6 голосов
/ 17 января 2011

Может быть, попробуйте IsVisibleChanged, хотя сам не использовал его.

Это событие не вызывается, если элемент не отображается системой макетов по причинам, отличным от значениясвойства IsVisible.Например, элемент может не иметь ассоциированного визуала.

4 голосов
/ 08 декабря 2013

Вы можете использовать событие IsVisibleChnaged. Назначить обработчик событий

MyUserControl.IsVisibleChanged += ScheduleUserControl_IsVisibleChanged;

В обработчике событий проверьте, является ли он видимым или нет.

void _IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if ((bool)e.NewValue)
    {
        //Visible
    }
    else
    {
        //Not Visible
    }
}
1 голос
/ 09 марта 2017

Вы можете использовать GotFocus Event

 <i:Interaction.Triggers>
        <i:EventTrigger EventName="GotFocus">
            <i:InvokeCommandAction Command="{Binding ContentControlLoadedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...