Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 视图如何知道在WPF中使用哪个ViewModel?_C#_Wpf_Mvvm - Fatal编程技术网

C# 视图如何知道在WPF中使用哪个ViewModel?

C# 视图如何知道在WPF中使用哪个ViewModel?,c#,wpf,mvvm,C#,Wpf,Mvvm,有人能解释一下视图和视图模型是如何连接的吗?我在任何地方都找不到引用ViewModel的视图的xaml或xaml.cs,也找不到引用视图的ViewModel.cs文件中的任何内容,但是它们以某种方式连接在一起,并且可以将成员从ViewModel绑定到视图 此外,在每个视图的构造函数中,只有视图的InitializeComponent和ViewModel的基本构造函数(没有视图的声明/定义) 谢谢 视图包含xaml中视图模型类的对象 InitializeComponent函数创建页面上的所有控件,

有人能解释一下视图和视图模型是如何连接的吗?我在任何地方都找不到引用ViewModel的视图的xaml或xaml.cs,也找不到引用视图的ViewModel.cs文件中的任何内容,但是它们以某种方式连接在一起,并且可以将成员从ViewModel绑定到视图

此外,在每个视图的构造函数中,只有视图的InitializeComponent和ViewModel的基本构造函数(没有视图的声明/定义)


谢谢

视图包含xaml中视图模型类的对象


InitializeComponent函数创建页面上的所有控件,设置样式等。

这里有各种选项

必须将视图的
DataContext
设置为ViewModel的实例。这里有很多选择:

  • 这可以直接在xaml中完成(视图只是直接引用ViewModel)
  • 这可以在视图的构造函数中完成(
    This.DataContext=new MyViewModel();
  • 这可以通过
    DataTemplate
  • “协调”类可以将它们连接在一起(即:一个单独的“presenter”类可以同时构造这两个类并适当地设置
    DataContext
最常见的方法是让视图在xaml中定义VM(视图优先),或者让一切都基于以ViewModel为中心的视图,并让WPF基于绑定的VM自动创建视图(ViewModel优先)

前一种方法是许多工具包使用的方法,例如。后一种方法是我在中使用的,也被其他一些工具包使用。

将视图连接到视图模型的“干净”方法是

创建视图时,对于每个视图,将其数据源设置为其视图模型:

例如

当您查看的模型发生更改时,请更新VM:

public class MainVM
{
    private void OnSelectedModelItemChanged()
    {
        this.SelectedItem = new ItemVM();
        this.SelectedItem.Model = this.SelectedModelItem;
    }
}

并使用数据模板使view为每个VM选择正确的子视图。

正如其他人已经显示的,有多个选项。当然,每当你听到多种选择时,你都会想知道每种选择的优缺点是什么。事实证明,除了一个以外,它们都有很大的缺点

下面的方法不涉及外部库,不涉及额外的内务管理类和接口,几乎没有魔法,而且非常灵活,因为您可以拥有包含其他ViewModel的viewmodels,并且可以实例化其中的每一个,这样您就可以将构造函数参数传递给它们

对于主窗口的viewmodel: 对于所有其他viewmodels: 这在MainViewModel.cs中:

using Collections = System.Collections.Generic;

public class MainViewModel
{
    public SomeViewModel SomeViewModel { get; }
    public OtherViewModel OtherViewModel { get; }
    public Collections.IReadOnlyList<string> Arguments { get; }
    
    public MainViewModel( Collections.IReadOnlyList<string> arguments )
    {
        Arguments = arguments;
        SomeViewModel = new SomeViewModel( this );
        OtherViewModel = new OtherViewModel( this );
    }
}
使用集合=System.Collections.Generic;
公共类主视图模型
{
公共SomeViewModel SomeViewModel{get;}
公共OtherViewModel OtherViewModel{get;}
public Collections.IReadOnlyList参数{get;}
public MainViewModel(Collections.IReadOnlyList参数)
{
参数=参数;
SomeViewModel=新的SomeViewModel(此);
OtherViewModel=新的OtherViewModel(此);
}
}
这在MainView.xaml中:

[...]
xmlns:local="clr-namespace:the-namespace-of-my-wpf-stuff"
[...]
    <local:SomeView DataContext="{Binding SomeViewModel}" />
    <local:OtherView DataContext="{Binding OtherViewModel}" />
[...]
[…]
xmlns:local=“clr名称空间:我的wpf内容的名称空间”
[...]
[...]

如您所见,viewmodel可以只是另一个viewmodel的成员(子级);在本例中,SomeViewModel和OtherViewModel是MainViewModel的子对象。然后,在MainView的XAML文件中,您可以实例化每个子视图,并通过
绑定到相应的子视图模型来指定它们的
DataContext

它会在哪里?我找不到任何包含单词“ViewModel”(这就是我的视图模型的名称)的文本。您可能需要查看Reed的回答。我这样做的方式是在视图的xaml中有一个viewmodel的对象。由于不清楚您是否使用了第三方MVVM框架,我怀疑您需要发布一些代码才能得到准确的答案。你可以用几十种不同的方式连接视图和视图模型,但我们看不到你面前有什么代码。我建议回到基础上来——我写了一个关于MVVM的系列文章,其中涵盖了一些基础知识,比如“什么是视图模型”和“什么是视图”以及它们是如何连接在一起的。可能值得略读:+1。这种“协调”类通常称为
Controller
(MVC模式)或
Presenter
(MVP模式),其中Presenter同时充当控制器和视图模型。走向MVP将意味着
视图模型将打开视图。@OlivierJacot Descombes,除非您使用数据模板,否则虚拟机确实需要打开视图。@DannyVarod如果您使用数据模板,WPF将有效地成为MVP术语中的“演示者”,为您协调这一点。然而,它将成为基于反射的通用演示者。@ReedCopsey谢谢!我找到了它所在的位置,它被嵌入到某个地方,这个地方调用了一些设置DataContext的东西。(虽然不是我会做的…)ViewModel已创建,然后在EventHandler中定义为视图的DataContext:s
using Collections = System.Collections.Generic;

public class MainViewModel
{
    public SomeViewModel SomeViewModel { get; }
    public OtherViewModel OtherViewModel { get; }
    public Collections.IReadOnlyList<string> Arguments { get; }
    
    public MainViewModel( Collections.IReadOnlyList<string> arguments )
    {
        Arguments = arguments;
        SomeViewModel = new SomeViewModel( this );
        OtherViewModel = new OtherViewModel( this );
    }
}
[...]
xmlns:local="clr-namespace:the-namespace-of-my-wpf-stuff"
[...]
    <local:SomeView DataContext="{Binding SomeViewModel}" />
    <local:OtherView DataContext="{Binding OtherViewModel}" />
[...]