视图关闭时如何停止视图模型中的调度计时器?
Posted
技术标签:
【中文标题】视图关闭时如何停止视图模型中的调度计时器?【英文标题】:How to stop a dispatchtimer in the viewmodel when the view is closed? 【发布时间】:2022-01-20 09:34:18 【问题描述】:当视图关闭时,我想关闭 ViewModel 中的计时器。
我的代码:
MainWindow.xaml.cs:
public MainWindow()
InitializeComponent();
this.DataContext = new UnitViewModel();
Console.WriteLine(System.AppDomain.CurrentDomain.BaseDirectory);
UnitViewModel.cs
class UnitViewModel : ObservableObject
DispatcherTimer dispatcherTimer = new DispatcherTimer();
public UnitViewModel()
StartTimer();
private void StartTimer()
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 600);
dispatcherTimer.Start();
private void dispatcherTimer_Tick(object sender, EventArgs e)
UpdateUnit();
有没有办法在 MainWindow 关闭时停止这个计时器?或者不再打开。我更喜欢在我的 viewModel 中有这段代码,有没有在 MVVM 中解决这个问题的好方法?
【问题讨论】:
视图模型应该公开一个停止计时器的 Shutdown 方法。应该从 MainWindow 中的 Closed 或 Closing 事件处理程序调用该方法。 【参考方案1】:向停止计时器的视图模型添加某种公共 API:
public void Stop() => dispatcherTimer.Stop();
从视图中以一种或另一种方式调用此方法。
例如,您可以在代码隐藏中处理事件或覆盖方法:
protected override void OnClosing(CancelEventArgs e)
base.OnClosing(e);
(DataContext as UnitViewModel)?.Stop();
...或在调用命令的 XAML 标记中使用 EventTrigger
:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing" >
<i:InvokeCommandAction Command="Binding StopCommand" />
</i:EventTrigger>
</i:Interaction.Triggers>
这两种方法都符合 MVVM 设计模式。
【讨论】:
【参考方案2】:就个人而言,我根本不会在视图模型中使用调度程序计时器。 我可能会改用异步和循环。 600 毫秒的延迟将由
引入await Task.Delay(600);
这将进入一个最适合的while循环。
我也会首先在单个窗口应用程序中使用视图模型,以便从该视图模型中对视图进行模板化。处理视图模型,视图消失。
如果它绝对必须是与视图模型的单独窗口,则使视图模型成为该视图的私有成员。关闭窗口并处理视图模型。如有必要,使用弱引用/事件将视图模型与任何模型分离。 不过,我的模型通常是 Web api。
【讨论】:
【参考方案3】:只需将您的窗口传递给 ViewModel 并将 Closing 事件绑定到 OnClosing 方法:
public class UnitViewModel
public UnitViewModel(Window w)
mainWindow = w;
mainWindow.Closing += OnMainWindowClosing;
private Window mainWindow;
private void OnMainWindowClosing(object sender, EventArgs e)
dispatcherTimer.Stop();
//anything else you want
public MainWindow()
InitializeComponent();
this.DataContext = new UnitViewModel(MainWindow);
Console.WriteLine(System.AppDomain.CurrentDomain.BaseDirectory);
【讨论】:
"将你的窗口传递给 ViewModel" 不是 MVVM。视图模型不知道视图,当然也不知道视图的任何特定事件,例如关闭。以上是关于视图关闭时如何停止视图模型中的调度计时器?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 MVC 模型动态过滤 javafx 中的列表视图控件,同时以多种方式更新? [关闭]