首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多线程视图模型

多线程视图模型
EN

Stack Overflow用户
提问于 2010-10-13 23:07:57
回答 1查看 221关注 0票数 1

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

每个Page使用一个单独的视图模型。

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

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

只要我不想回到向导中,所有这些都可以正常工作。但如果我这样做了,页面就不再有DataContext,也不会显示任何内容,因为它以前已经卸载过。

因此,要解决这个问题,我不需要在卸载时处理DataContext,而是指示视图模型在其拥有的窗口加载/卸载时启动/停止它的线程。为此,我需要在视图模型上引入几个方法(比如Start()和Stop())来实现这一点。并从页面的初始化和卸载处理程序调用这些方法。

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

请帮帮康斯坦丁

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-10-13 23:57:07

听起来问题似乎是视图模型依赖于视图的生命周期-这自动意味着视图将通知视图模型状态转换。我们的目标是找到这些变化的最佳代表。

第一步是重新构建交互:Start()Stop()是势在必行的概念,我同意,这确实让人感觉沉重。相反,让我们考虑一下我们作为状态机在做什么。我假设您的线程正在进行某种侦听,因此我们的状态可能是ListeningIdleComplete。它们将分别对应于正在运行的线程、暂停的线程和准备终止的线程。

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

代码语言:javascript
复制
public enum ListenerState
{
    Idle,

    Listening,

    Complete
}

您可以在视图模型上声明此类型的属性:

代码语言:javascript
复制
public class ListenerModel : ViewModel
{
    private ListenerState _state;

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

            RaisePropertyChanged("State");
        }
    }
}

然后,您将监听状态的更改并更新线程以匹配:

代码语言:javascript
复制
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
    if(e.PropertyName == "State")
    {
        // Manipulate thread for current state
    }
}

现在,视图只需通知视图模型生命周期事件(除了视图之外,视图模型不能通过任何其他方式了解这些事件):

代码语言:javascript
复制
private void OnLoaded(object sender, RoutedEventArgs e)
{
    ((ListenerModel) this.DataContext).State = ListenerState.Listening;
}

如果要将视图与视图模型完全分离,可以在控件中为状态创建依赖属性:

代码语言:javascript
复制
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处理程序中设置该属性,而不是引用视图模型:

代码语言:javascript
复制
private void OnLoaded(object sender, RoutedEventArgs e)
{
    this.ListenerState = ListenerState.Listening;
}

最后,将属性绑定到标记中的视图模型的属性:

代码语言:javascript
复制
<local:YourControl ListenerState="{Binding State, Mode=TwoWay}" />
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3925141

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档