增加ViewModelBase 生命周期控制View

This commit is contained in:
chfei committed 2026-11-13 11:07:41 +08:00
1 parent 30a6a5ea24
commit 9b9e4cbd82
8 files changed
+163 -8

No files matched your search

@@ -32,7 +32,7 @@ public static class IDialogServiceExtension
/// <summary>
/// 确定取消对话框 ViewModel
/// </summary>
public class ConfirmDialogViewModel : BindableBase, IDialogAware
public class ConfirmDialogViewModel : ViewModelBase, IDialogAware
{
public ConfirmDialogViewModel()
{
@@ -286,4 +286,4 @@ public abstract class ConfirmDialogViewModel<TParameter, TResult> : ConfirmDialo
//public abstract class ConfirmDialogParameterViewModel : ConfirmDialogViewModel<ConfirmDialogParameterViewModel.Parameter>
//{
// public abstract class Parameter;
//}
//}
@@ -0,0 +1,85 @@
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?.OnLoaded();
}
private static void OnUnloaded(object sender, RoutedEventArgs e)
{
var view = (FrameworkElement)sender;
var previous = (ViewModelBase?)view.GetValue(LoadedViewModelProperty);
view.ClearValue(LoadedViewModelProperty);
previous?.OnUnloaded();
}
}
@@ -0,0 +1,14 @@
using Prism.Mvvm;
using System.ComponentModel;
namespace Store.Management.Framework.Controls;
public abstract class ViewModelBase : BindableBase
{
protected internal virtual void OnLoaded() { }
protected internal virtual void OnUnloaded() { }
protected internal virtual void OnActivated() { }
protected internal virtual void OnDeactivated() { }
protected internal virtual void OnClosing(CancelEventArgs e) { }
protected internal virtual void OnClosed() { }
}
@@ -26,6 +26,8 @@ public abstract class FrameworkApplication : PrismApplication
private IStatusBarService StatusBarService;
private IMessageBoxService MessageBoxService;
private static bool FatalShutdown = false;
static FrameworkApplication() => Controls.ViewLifecycle.Register();
protected FrameworkApplication()
{
DispatcherUnhandledException += OnDispatcherUnhandledException;