86 lines
3.5 KiB
C#
86 lines
3.5 KiB
C#
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();
|
|
}
|
|
}
|