MVVM 在 ViewModel 构建期间或之后加载数据? [英] MVVM load data during or after ViewModel construction?

查看:22
本文介绍了MVVM 在 ViewModel 构建期间或之后加载数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的一般问题是如标题所述,最好在 ViewModel 构建期间加载数据还是之后通过一些 Loaded 事件处理加载数据?

My generic question is as the title states, is it best to load data during ViewModel construction or afterward through some Loaded event handling?

我猜答案是在通过一些 Loaded 事件处理构建之后,但我想知道如何在 ViewModel 和 View 之间进行最干净的协调?

I'm guessing the answer is after construction via some Loaded event handling, but I'm wondering how that is most cleanly coordinated between ViewModel and View?

以下是有关我的情况和我正在尝试解决的特定问题的更多详细信息:

Here's more details about my situation and the particular problem I'm trying to solve:

我使用 MVVM Light 框架以及 Unity 进行 DI.我有一些嵌套的视图,每个都绑定到相应的 ViewModel.ViewModel 通过 Laurent Bugnion 放入 MVVM Light 的 ViewModelLocator 思想绑定到每个 View 的根控件 DataContext.这允许通过静态资源查找 ViewModels 并通过依赖注入框架控制 ViewModels 的生命周期,在这种情况下是 Unity.它还允许 Expression Blend 查看与 ViewModel 相关的所有内容以及如何绑定它们.

I am using the MVVM Light framework as well as Unity for DI. I have some nested Views, each bound to a corresponding ViewModel. The ViewModels are bound to each View's root control DataContext via the ViewModelLocator idea that Laurent Bugnion has put into MVVM Light. This allows for finding ViewModels via a static resource and for controlling the lifetime of ViewModels via a Dependency Injection framework, in this case Unity. It also allows for Expression Blend to see everything in regard to ViewModels and how to bind them.

所以无论如何,我有一个父视图,它有一个 ComboBox 数据绑定到它的 ViewModel 中的 ObservableCollection.ComboBox 的 SelectedItem 也绑定(双向)到 ViewModel 上的一个属性.当 ComboBox 的选择发生变化时,这是触发其他视图和子视图的更新.目前,我正在通过 MVVM Light 中的消息系统完成此操作.当您在 ComboBox 中选择不同的项目时,这一切都很好,并且符合预期.

So anyway, I've got a parent View that has a ComboBox databound to an ObservableCollection in its ViewModel. The ComboBox's SelectedItem is also bound (two-way) to a property on the ViewModel. When the selection of the ComboBox changes, this is to trigger updates in other views and subviews. Currently I am accomplishing this via the Messaging system that is found in MVVM Light. This is all working great and as expected when you choose different items in the ComboBox.

但是,ViewModel 在构建期间通过一系列初始化方法调用获取其数据.如果我想控制 ComboBox 的初始 SelectedItem 是什么,这似乎只是一个问题.使用 MVVM Light 的消息传递系统,我目前设置了 ViewModel 的 SelectedItem 属性的 setter 是广播更新的那个,而另一个感兴趣的 ViewModel 在它们的构造函数中注册消息.看来我目前正在尝试在构建时通过 ViewModel 设置 SelectedItem,这还不允许构建和注册子 ViewModel.

However, the ViewModel is getting its data during construction time via a series of initializing method calls. This seems to only be a problem if I want to control what the initial SelectedItem of the ComboBox is. Using MVVM Light's messaging system, I currently have it set up where the setter of the ViewModel's SelectedItem property is the one broadcasting the update and the other interested ViewModels register for the message in their constructors. It appears I am currently trying to set the SelectedItem via the ViewModel at construction time, which hasn't allowed sub-ViewModels to be constructed and register yet.

在 ViewModel 中协调 SelectedItem 的数据加载和初始设置的最简洁方法是什么?我真的想坚持在视图的代码隐藏中尽可能少地放置合理的.我想我只需要一种方法让 ViewModel 知道什么时候加载了东西,然后它可以继续加载数据并完成设置阶段.

What would be the cleanest way to coordinate the data load and initial setting of SelectedItem within the ViewModel? I really want to stick with putting as little in the View's code-behind as is reasonable. I think I just need a way for the ViewModel to know when stuff has Loaded and that it can then continue to load the data and finalize the setup phase.

预先感谢您的回复.

推荐答案

对于事件,您应该使用 MVVM Light Toolkit 中的 EventToCommand.使用它,您可以将任何 ui 元素的任何事件绑定到relaycommand.在

For events you should use the EventToCommand in MVVM Light Toolkit. Using this you can bind any event of any ui element to relaycommand. Check out his article on EventToCommand at

http://blog.galasoft.ch/archive/2009/11/05/mvvm-light-toolkit-v3-alpha-2-eventtocommand-behavior.aspx

下载示例并查看.这很棒.那时您将不需要任何代码隐藏.一个例子如下:

Download the sample and have a look. Its great. You won't need any codebehind then. An example is as follows:

<Page x:Class="cubic.cats.Wpf.Views.SplashScreenView"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
      xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras"
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
    Title="SplashScreenPage">

    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <cmd:EventToCommand Command="{Binding LoadedCommand}" />
        </i:EventTrigger>        
    </i:Interaction.Triggers>

    <Grid>
        <Label Content="This is test page" />
    </Grid>
</Page>

和视图模式可能是这样的

and the view mode could be like this

 public class SplashScreenViewModel : ViewModelBase
    {
        public RelayCommand LoadedCommand
        {
            get;
            private set;
        }

        /// <summary>
        /// Initializes a new instance of the SplashScreenViewModel class.
        /// </summary>
        public SplashScreenViewModel()
        {
            LoadedCommand = new RelayCommand(() =>
            {
                string a = "put a break point here to see that it gets called after the view as been loaded";
            });
        }
    }

如果您希望视图模型具有 EventArgs,您可以简单地将 PassEventArgsToCommand 设置为 true:

if you would like the view model to have the EventArgs, you can simple set PassEventArgsToCommand to true:

<i:Interaction.Triggers>
            <i:EventTrigger EventName="Loaded">
                <cmd:EventToCommand PassEventArgsToCommand="True" Command="{Binding LoadedCommand}" />
  </i:EventTrigger>        
</i:Interaction.Triggers>

视图模型将像

public class SplashScreenViewModel : ViewModelBase
{
    public RelayCommand<MouseEventArgs> LoadedCommand
    {
        get;
        private set;
    }

    /// <summary>
    /// Initializes a new instance of the SplashScreenViewModel class.
    /// </summary>
    public SplashScreenViewModel()
    {
        LoadedCommand = new RelayCommand<MouseEventArgs>(e =>
        {
            var a = e.WhateverParameters....;
        });
    }

}

这篇关于MVVM 在 ViewModel 构建期间或之后加载数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆