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
0 comments:
Post a Comment