gpt4 book ai didi

wpf - 多线程 View 模型

转载 作者:行者123 更新时间:2023-12-03 10:40:43 24 4
gpt4 key购买 nike

我有一个实现向导功能的 NavigationWindow,以及一组代表步骤的 Page 对象。

每个 Page 使用单独的 View 模型。

其中一些 View 模型从它们的构造函数中产生工作线程。我在处理 View 模型时终止这些线程(它们实现 IDisposable)。

此外,我在 Pages 的构造函数中将这些 View 模型分配给 Pages 的 DataContext,并在 Unloaded 事件上处理 DataContext。我这样做是因为我需要停止工作线程。

只要我不想在向导中导航回来,所有这些都可以正常工作。但如果我这样做了,该页面,因为它之前已被卸载,不再有 DataContext 并且不显示任何内容。

所以,为了解决这个问题,我不需要在卸载时处理 DataContext,而是指示 View 模型在其拥有的窗口被加载/卸载时启动/停止其线程。我认为我需要在 View 模型上引入一些方法(例如,Start() 和 Stop())来做到这一点。并从 Pages 的 Initialized 和 Unloaded 处理程序中调用这些方法。

但这很丑陋。它太复杂了,页面需要知道启动/停止线程,否则它将无法工作。所以我正在寻找正确的 MVVM 方法来实现这一点。

请帮忙
康斯坦丁

最佳答案

听起来问题在于 View 模型依赖于 View 的生命周期——这自动意味着 View 将通知 View 模型状态转换。目标是找到这些变化的最佳表示。

第一步是重新构建交互:Start()Stop()是命令式的概念,我同意,确实感觉很重。相反,让我们考虑一下我们作为状态机正在做什么。我假设你的线程正在做某种监听,所以我们的状态可能是 Listening , Idle , 和 Complete .它们将分别对应于正在运行的线程、暂停的线程和准备终止的线程。

一种表示状态的可靠方法是枚举:

public enum ListenerState
{
Idle,

Listening,

Complete
}

您将在 View 模型上声明此类型的属性:
public class ListenerModel : ViewModel
{
private ListenerState _state;

public ListenerState State
{
get { return _state; }
set
{
_state = value;

RaisePropertyChanged("State");
}
}
}

然后,您将监听状态变化并更新线程以匹配:
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
if(e.PropertyName == "State")
{
// Manipulate thread for current state
}
}

现在, View 只需要通知 View 模型生命周期事件(除了 View 之外, View 模型无法知道其他任何方式):
private void OnLoaded(object sender, RoutedEventArgs e)
{
((ListenerModel) this.DataContext).State = ListenerState.Listening;
}

如果您想将 View 与 View 模型完全分离,您可以在控件中为状态创建一个依赖属性:
public static readonly DependencyProperty ListenerStateProperty =
DependencyProperty.Register("ListenerState", typeof(ListenerState), typeof(YourControl), null);

public ListenerState ListenerState
{
get { return (ListenerState) GetValue(ListenerStateProperty); }
set { SetValue(ListenerStateProperty, value); }
}

然后,在 Loaded 中设置该属性处理程序而不是引用 View 模型:
private void OnLoaded(object sender, RoutedEventArgs e)
{
this.ListenerState = ListenerState.Listening;
}

最后,您可以在标记中将该属性绑定(bind)到 View 模型的属性:
<local:YourControl ListenerState="{Binding State, Mode=TwoWay}" />

关于wpf - 多线程 View 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3925141/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com