增加ViewModelBase 生命周期控制View
This commit is contained in:
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;
|
||||
|
||||
Reference in new issue
Block a user