Sunday, August 5, 2018

How do I assign a global initialized event?

Leave a Comment

I've got this code in my App.xaml.cs:

protected override void OnStartup(StartupEventArgs e) {     EventManager.RegisterClassHandler(typeof(TextBox), TextBox.TextChangedEvent, new RoutedEventHandler(TextBox_TextChangedEvent)); } private void TextBox_TextChangedEvent(object sender, RoutedEventArgs e) {     // Works } 

I would like to do something similar for the InitializedEvent.
Here's my failed attempt:

protected override void OnStartup(StartupEventArgs e) {     EventManager.RegisterClassHandler(typeof(FrameworkElement), FrameworkElement.InitializedEvent, new EventHandler(FrameworkElement_InitializedEvent)); } private void FrameworkElement_InitializedEvent(object sender, EventArgs e) {  } 

Is the InitializedEvent somewhere else?
Is this even possible?

I've tried using the LoadedEvent:

protected override void OnStartup(StartupEventArgs e) {     EventManager.RegisterClassHandler(typeof(FrameworkElement), FrameworkElement.LoadedEvent, new RoutedEventHandler(FrameworkElement_LoadedEvent)); } private void FrameworkElement_LoadedEvent(object sender, RoutedEventArgs e) {     // Fires only for Windows } 

It only fired for Windows and not the controls inside the Windows. I did realize though; that when I added a loaded event to a Label that I had inside my Window; the global FrameworkElement_LoadedEvent fired for that Label even though my normal loaded event (That I made for the Label specifically) was empty. I've also tried these:

EventManager.RegisterClassHandler(typeof(Button), Button.LoadedEvent, new RoutedEventHandler(Button_LoadedEvent)); EventManager.RegisterClassHandler(typeof(Grid), Grid.LoadedEvent, new RoutedEventHandler(Grid_LoadedEvent)); EventManager.RegisterClassHandler(typeof(DataGrid), DataGrid.LoadedEvent, new RoutedEventHandler(DataGrid_LoadedEvent)); 

But they don't fire unless I add another empty loaded event on those controls specifically.

My goal is to build up a sort of a time log of every control that becomes initialized.

How can I achieve this without adding loaded events on every single control I have?

(I have a lot)

1 Answers

Answers 1

Here you are!

public partial class App : Application {     // ##############################################################################################################################     // Constructor     // ##############################################################################################################################      #region Constructor      static App()     {         // set MyInitialized=true for new windows (happens before Loaded)         EventManager.RegisterClassHandler(typeof(Window), FrameworkElement.SizeChangedEvent, new RoutedEventHandler(OnSizeChanged));          // our loaded handler         EventManager.RegisterClassHandler(typeof(UIElement), FrameworkElement.LoadedEvent, new RoutedEventHandler(OnLoaded), true);         EventManager.RegisterClassHandler(typeof(ContentElement), FrameworkContentElement.LoadedEvent, new RoutedEventHandler(OnLoaded), true);     }      private static void OnSizeChanged(object sender, RoutedEventArgs e)     {         //Console.WriteLine("SizeChanged {0}", sender);         SetMyInitialized((Window) sender, true);     }      private static void OnLoaded(object sender, RoutedEventArgs e)     {         Trace.WriteLine($"{DateTime.Now:O}: {sender} loaded");     }      #endregion      // ##############################################################################################################################     // MyInitialized     // ##############################################################################################################################      #region MyInitialized      public static void SetMyInitialized(UIElement element, bool value)     {         element.SetValue(MyInitializedProperty, value);     }      public static bool GetMyInitialized(UIElement element)     {         return (bool) element.GetValue(MyInitializedProperty);     }      public static readonly DependencyProperty MyInitializedProperty = DependencyProperty.RegisterAttached("MyInitialized", typeof (bool), typeof (App), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits, OnMyInitializedChanged));      private static void OnMyInitializedChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs ev)     {         if ((bool)ev.NewValue)         {             // registering instance handler unbreaks class handlers             if (dpo is FrameworkElement element)                 element.Loaded += _EmptyRoutedEventHandler;             if (dpo is FrameworkContentElement contentElement)                 contentElement.Loaded += _EmptyRoutedEventHandler;         } else         {             throw new ArgumentException("Cannot set to false", ev.Property.Name);         }         //Console.WriteLine("MyInitialized {0} {1}=>{2}", dpo, ev.OldValue, ev.NewValue);     }      private static readonly RoutedEventHandler _EmptyRoutedEventHandler = delegate { };      #endregion               } 

XAML

<Window x:Class="WpfApp3.MainWindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         xmlns:local="clr-namespace:WpfApp3"         mc:Ignorable="d"         Title="MainWindow" Height="450" Width="800"         d:DataContext="{d:DesignInstance local:MainWindow}">         <Grid>             <Border Background="Green" VerticalAlignment="Center" HorizontalAlignment="Center" Width="30" Height="20">                 <TextBlock Background="Orange" Text="hello"></TextBlock>             </Border>         </Grid> </Window> 

Sample Console output:

2018-07-31T14:20:52.6052225+02:00: WpfApp3.MainWindow loaded 2018-07-31T14:20:52.6112064+02:00: System.Windows.Controls.Border loaded 2018-07-31T14:20:52.6132008+02:00: System.Windows.Documents.AdornerDecorator loaded 2018-07-31T14:20:52.6141984+02:00: System.Windows.Controls.ContentPresenter loaded 2018-07-31T14:20:52.6141984+02:00: System.Windows.Controls.Grid loaded 2018-07-31T14:20:52.6151966+02:00: System.Windows.Controls.Border loaded 2018-07-31T14:20:52.6161935+02:00: System.Windows.Controls.TextBlock loaded 2018-07-31T14:20:52.6161935+02:00: System.Windows.Documents.AdornerLayer loaded 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment