旧的ViewModels捕获事件

时间:2017-08-09 13:31:32

标签: c# winforms events mvvm

我正在制作Winforms程序,使用类似MVVM的模式。我的所有数据都连接到SessionModel,传递给所有ViewModels(我知道这可能不是最好的做事方式,但这就是我得到的)。

我的问题是:在ViewModel内部我有一个事件监听器,它将事件连接到方法,如下所示:

// Base constructor
public MyViewModel(SessionModel session) 
{
    this.session = session;
    MyUserControl.MyEvent_OnActivate += AddItem;
}

// This method should be called, whenever the event is invoked
private void AddItem() 
{
    session.Items.AddItem();
}

每次显示相应的View时,都会生成ViewModel的新实例。这就产生了我的问题。因为一切都很好第一次我加载了ViewViewModel。但是第二次我访问它时,第一个实例仍然存在(虽然没有在任何地方引用),因此也接收了事件。结果是方法AddItem()被称为两次(一次来自ViewModel的每个实例。如果我再次导航到View,它将是三次打电话,等等。

我的ViewViewModel是从MainForm加载的,如下所示:

// When called, this method loads the view and view model
private void ShowMyView() 
{
    MyViewModel viewModel = new MyViewModel(session);
    MyView view = new MyView(viewModel);
    ShowContent(view);
}

// Clears content panel and shows new view
private void ShowContent(UserControl view)
{
    while (pnlContent.Controls.Count > 0)
    {
        pnlContent.Controls[0].Dispose();
    }
     pnlContent.Controls.Add(view);
}

是否有一些清除视图模型旧实例的聪明方法,因为垃圾收集显然不够快?

3 个答案:

答案 0 :(得分:0)

  

虽然没有在任何地方引用......

事件订阅确实可以引用订阅者。无论何时初始化新视图模型,旧视图模型都应取消订阅MyUserControl.MyEvent_OnActivate。使ViewModel处于一次性状态,并使用Dispose方法执行清理。

答案 1 :(得分:0)

我找到了一个解决方案,删除了event并直接聆听delegate,如this post中所述。

然后代码如下:

public class MyUserControl
{
    internal delegate void MyDelegate();
    (...)
}

public class MyViewModel
{
    public MyVieWModel(SessionModel session)
    {
        this.session = session;
        MyUserControl.MyDelegate = AddItem;
    }

    public void AddItem()
    {
        (...)
    }
}

答案 2 :(得分:0)

MyControl仍然保留对先前视图模型的引用的问题。

Winforms完全适合MVVM模式。它支持data-binding(不像WPF那么强大)

  

我知道我正在扼杀MVVM,就像我一样使用它。它   是一个解决方案,因为我的观点包含用户控件,我有   到"跟"视图模型,他们不知道

通过在viewmodel中引用视图控件,可以打破MVVM模式。如果你继续"关注" MVVM - 你是独立的,不同类型的问题开始聚集,几周后你决定MVVM模式不可行;)

对于您的特定情况的简单建议,在不了解应用程序上下文的情况下,用户控制现在应该关注它所影响的视图模型。

您可以将视图模型的集合绑定到用户控件,只需在其中调用它的方法

private UserControl_OnActivate()
{
    foreach (var viewmodel in ViewModels)
    {
        viewmodel.AddItem()
    }
}

现在用户控件知道viewmodel和viewmodel对用户控件(视图)一无所知 - MVVM模式。
当您使用新的ViewModels集合更新时,旧的viewmodel引用将被垃圾收集。