using Prism.Services.Dialogs; using System.ComponentModel; using System.Windows; using System.Windows.Controls; namespace Store.Management.Framework.Controls; internal static class ViewLifecycle { // 卸载时 DataContext 可能已改变,记录实际收到 OnLoaded 的实例。 private static readonly DependencyProperty LoadedViewModelProperty = DependencyProperty.RegisterAttached("LoadedViewModel", typeof(ViewModelBase), typeof(ViewLifecycle)); internal static void Register() { foreach (Type type in new[] { typeof(UserControl), typeof(Window) }) { FrameworkElement.DataContextProperty.OverrideMetadata(type, new FrameworkPropertyMetadata(null, OnDataContextChanged)); } } private static void OnDataContextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { if (sender is Window window) { if (e.OldValue is ViewModelBase) { window.Activated -= OnActivated; window.Deactivated -= OnDeactivated; window.Closing -= OnClosing; window.Closed -= OnClosed; } if (e.NewValue is ViewModelBase) { window.Activated += OnActivated; window.Deactivated += OnDeactivated; window.Closing += OnClosing; window.Closed += OnClosed; } if (window is IDialogWindow) return; // Prism 弹窗由内容页接收加载与卸载。 } var view = (FrameworkElement)sender; if (e.OldValue is ViewModelBase) { view.Loaded -= OnLoaded; view.Unloaded -= OnUnloaded; } if (e.NewValue is ViewModelBase) { view.Loaded += OnLoaded; view.Unloaded += OnUnloaded; } if (view.IsLoaded || view.GetValue(LoadedViewModelProperty) != null) UpdateViewModel(view); } private static void OnLoaded(object sender, RoutedEventArgs e) => UpdateViewModel((FrameworkElement)sender); private static void OnActivated(object? sender, EventArgs e) => (((Window)sender!).DataContext as ViewModelBase)?.OnActivated(); private static void OnDeactivated(object? sender, EventArgs e) => (((Window)sender!).DataContext as ViewModelBase)?.OnDeactivated(); private static void OnClosing(object? sender, CancelEventArgs e) => (((Window)sender!).DataContext as ViewModelBase)?.OnClosing(e); private static void OnClosed(object? sender, EventArgs e) => (((Window)sender!).DataContext as ViewModelBase)?.OnClosed(); private static void UpdateViewModel(FrameworkElement view) { // 共享父级 DataContext 的页眉、导航栏等子控件不拥有页面生命周期。 var source = DependencyPropertyHelper.GetValueSource(view, FrameworkElement.DataContextProperty); var next = source.BaseValueSource == BaseValueSource.Inherited ? null : view.DataContext as ViewModelBase; var previous = (ViewModelBase?)view.GetValue(LoadedViewModelProperty); if (ReferenceEquals(previous, next)) return; view.SetValue(LoadedViewModelProperty, next); previous?.OnUnloaded(); next?.NotifyLoaded(); } private static void OnUnloaded(object sender, RoutedEventArgs e) { var view = (FrameworkElement)sender; var previous = (ViewModelBase?)view.GetValue(LoadedViewModelProperty); view.ClearValue(LoadedViewModelProperty); previous?.OnUnloaded(); } }