增加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

@@ -58,8 +58,46 @@ class Program
Console.WriteLine("PASS: LoginViewModel -> ILoginService -> AuthApi, retry, password contract and cancellation.");
return 0;
}
App app = args.Contains("--status-bar") ? new App() : new TestApp(client);
App app = args.Contains("--status-bar") || args.Contains("--view-lifecycle") ? new App() : new TestApp(client);
app.InitializeComponent();
if (args.Contains("--view-lifecycle"))
{
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
var pageVm = new LifecycleProbe();
var windowVm = new LifecycleProbe();
var page = new UserControl { DataContext = pageVm, Content = new UserControl() };
var window = new Window { DataContext = windowVm, Content = page };
window.Show();
app.Dispatcher.Invoke(() => { }, DispatcherPriority.ApplicationIdle);
Check(pageVm.Loads == 1 && windowVm.Loads == 1, $"窗口和页面各加载一次:{windowVm.Loads}/{pageVm.Loads}");
window.Content = null;
app.Dispatcher.Invoke(() => { }, DispatcherPriority.ApplicationIdle);
Check(pageVm.Unloads == 1, "移出页面触发卸载");
window.Content = page;
app.Dispatcher.Invoke(() => { }, DispatcherPriority.ApplicationIdle);
Check(pageVm.Loads == 2, "重新加入页面再次加载");
var replacement = new LifecycleProbe();
page.DataContext = replacement;
Check(pageVm.Unloads == 2 && replacement.Loads == 1, "已加载的页面更换 ViewModel 后转移通知");
windowVm.CancelClose = true;
window.Close();
Check(window.IsVisible && windowVm.Closes == 0, "ViewModel 可以取消关闭");
windowVm.CancelClose = false;
window.Close();
Check(windowVm.Closes == 1, "窗口关闭后通知 ViewModel");
var dialogVm = new LifecycleProbe();
var dialog = new DialogWindow
{
DataContext = dialogVm,
Content = new UserControl { DataContext = dialogVm }
};
dialog.Show();
app.Dispatcher.Invoke(() => { }, DispatcherPriority.ApplicationIdle);
Check(dialogVm.Loads == 1, "Prism 弹窗宿主和内容共享 ViewModel 时只加载一次");
dialog.Close();
Console.WriteLine("PASS: view and window lifecycle.");
return 0;
}
int exitCode = 0;
app.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(async () =>
{
@@ -227,6 +265,18 @@ class Program
static void Check(bool success, string message) { if (!success) throw new Exception(message); }
}
sealed class LifecycleProbe : ViewModelBase
{
public int Loads { get; private set; }
public int Unloads { get; private set; }
public int Closes { get; private set; }
public bool CancelClose { get; set; }
protected override void OnLoaded() => Loads++;
protected override void OnUnloaded() => Unloads++;
protected override void OnClosing(System.ComponentModel.CancelEventArgs e) => e.Cancel = CancelClose;
protected override void OnClosed() => Closes++;
}
sealed class LoginHandler : HttpMessageHandler
{
public int RequestCount { get; private set; }