一、引言
在WPF的上位机开发中,当我们一个程序中有多个画面,在每个后面的后台可能需要多个进程需要对下位机的数据进行重复的读取或者处理,但当切换不同的界面后,page界面没有在视觉树上,那么需要结束后台的进程,若不结束那么再次回到该界面后台的进程将会重新拉起,极大的消耗内存。
二、基本思路:
在ViewModel中直接使用OnClosed
方法并不直接可行,OnClosed
是Window
类的一个受保护方法,用于处理窗口关闭事件。ViewModel通常不直接引用View(如Window或UserControl),而是通过数据绑定和命令来交互。
View中Loaded
和Unloaded
事件,并在事件处理程序中调用ViewModel中的一个方法,当page页面没有在视觉树上时,调用后台的关闭线程函数,销毁当前的线程。
三、示例代码
该示例是在page2viewmodel中进行了定时器操作,每隔一定的时间会执行一定的内容。需要对Timer_Tick这个线程进行关闭
public Page2ViewModel()
{
Page2Model.LineSeriesValues = new ChartValues<double> { 100, 100, 100, 100, 320, 540, 650, 444, 555 };
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1); // 设置间隔为1秒
timer.Tick += Timer_Tick; // 绑定Tick事件到处理方法
timer.Start(); // 启动定时器
}
private void Timer_Tick(object sender, EventArgs e)
{
// 在这里执行你的操作
Debug.WriteLine("page2定时器线程");
}
public void CloseTimer()
{
timer.Stop();
}
使用Loaded
和Unloaded
事件
每个页面(Page)都有Loaded
和Unloaded
事件,这些事件在页面被加载到视觉树中和从视觉树中移除时触发。然而,这些事件并不直接指示页面是否“在显示”,因为页面可能在后台被加载或卸载,但用户仍然可以看到它(如果它是在一个未激活的标签页中)。
public MyPage()
{
InitializeComponent();
this.Loaded += MyPage_Loaded;
this.Unloaded += MyPage_Unloaded;
}
private void MyPage_Loaded(object sender, RoutedEventArgs e)
{
// 页面被加载到视觉树中
// 注意:这不一定意味着页面是可见的或活动的
}
private void MyPage_Unloaded(object sender, RoutedEventArgs e)
{
// 页面从视觉树中移除
// 清理资源等操作
}
但在无法直接调用ViewModl中的函数,需要先获取到这个DataContext
作为ViewModel
的实例,然后再调用其方法。
在你的视图(View)的后台代码(CS文件)中,当你设置DataContext
之后,你可以这样调用CloseTimer()
方法
public partial class MyPage : Page
{
public MyPage()
{
InitializeComponent();
// 设置 DataContext
this.DataContext = new Page2ViewModel();
// 调用 DataContext 中的 CloseTimer 方法
// 首先,将 DataContext 转换为 Page2ViewModel 类型
if (this.DataContext is Page2ViewModel viewModel)
{
viewModel.CloseTimer();
}
}
// ... 其他方法和事件处理器
}
所以在MyPage_Unloaded事件中放入if (this.DataContext is Page2ViewModel viewModel) 就可调用viewmodl中的函数
public Page2()
{
InitializeComponent();
this.DataContext = new Page2ViewModel();
this.Loaded += MyPage_Loaded;
this.Unloaded += MyPage_Unloaded;
}
private void MyPage_Loaded(object sender, RoutedEventArgs e)
{
// 页面被加载到视觉树中
// 注意:这不一定意味着页面是可见的或活动的
}
private void MyPage_Unloaded(object sender, RoutedEventArgs e)
{
// 页面从视觉树中移除
Debug.WriteLine("Page2视觉树移除");
if (this.DataContext is Page2ViewModel Page2viewModel)
{
Page2viewModel.CloseTimer();
}
}