Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.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
WPF MVVM和将viewmodels传递给视图_Wpf_Mvvm - Fatal编程技术网

WPF MVVM和将viewmodels传递给视图

WPF MVVM和将viewmodels传递给视图,wpf,mvvm,Wpf,Mvvm,我是WPF的新手,现在我正在尝试适应MVVM模式。现在,我有一个简单的应用程序,其中我有一组视图模型,显示在网格中。双击网格中的行时,我希望显示ViewModel的详细视图 我现在遇到的问题是,我已经有了一个完全实例化的ViewModel,但我似乎无法将其传递到视图中。当我尝试加载该视图时,它显示为空。我已经发现,这是因为当加载视图时,它会创建自己的备份视图模型实例。因此,显然我需要绕过这种行为,并在创建实例ViewModel时以某种方式将其传递到视图中。我可以在视图中使用一个构造函数,它接受一

我是WPF的新手,现在我正在尝试适应MVVM模式。现在,我有一个简单的应用程序,其中我有一组视图模型,显示在网格中。双击网格中的行时,我希望显示ViewModel的详细视图

我现在遇到的问题是,我已经有了一个完全实例化的ViewModel,但我似乎无法将其传递到视图中。当我尝试加载该视图时,它显示为空。我已经发现,这是因为当加载视图时,它会创建自己的备份视图模型实例。因此,显然我需要绕过这种行为,并在创建实例ViewModel时以某种方式将其传递到视图中。我可以在视图中使用一个构造函数,它接受一个ViewModel并在其中设置数据源。但是,采用这种方法意味着我需要在ViewModel中构造视图,从而使ViewModel知道该视图。这是我想要避免的,因为我试图维护MVVM模式

那么在这种情况下我该怎么办?我应该打破MVVM模式,还是有一些好的、干净的解决方案适合MVVM模式?

有很多方法可以将视图模型传递给视图(如您所称),或者将视图模型设置为窗口或用户控件(如其他人所称)的DataContext。最简单的就是:

在视图构造函数中:

public partial class SomeView
{
    InitializeComponent();
    DataContext = new SomeViewModel();
}
更具MVVM的方法可能是在App.xaml中为每个视图模型定义DataTemplates,该视图模型定义了每个视图将使用的视图:

<DataTemplate DataType="{x:Type YourViewModelsPrefix:YourViewModel">
    <YourViewsPrefix:YourView />
</DataTemplate>
...
<DataTemplate DataType="{x:Type YourViewModelsPrefix:AnotherViewModel">
    <YourViewsPrefix:AnotherView />
</DataTemplate>
甚至在这样的收藏中:

<ContentControl Content="{Binding YourViewModelProperty}" />
<ListBox ItemsSource="{Binding YourViewModelCollectionProperty}" />
public class ViewFactory
{
    public UIElement Create(object context)
    {
        // Create the view model
        // You can pass in various information by parameters
        // as I do with context (Constructor Injection)
        var viewModel = new ViewModel(context);

        // Create the view and set the view model as data context
        var view = new View { DataContext = viewModel };
        return view;
    }
}
有许多方法可以将视图模型传递给视图(您称之为视图),或者将视图模型设置为窗口或用户控件的DataContext(其他人可能称之为)。最简单的就是:

在视图构造函数中:

public partial class SomeView
{
    InitializeComponent();
    DataContext = new SomeViewModel();
}
更具MVVM的方法可能是在App.xaml中为每个视图模型定义DataTemplates,该视图模型定义了每个视图将使用的视图:

<DataTemplate DataType="{x:Type YourViewModelsPrefix:YourViewModel">
    <YourViewsPrefix:YourView />
</DataTemplate>
...
<DataTemplate DataType="{x:Type YourViewModelsPrefix:AnotherViewModel">
    <YourViewsPrefix:AnotherView />
</DataTemplate>
甚至在这样的收藏中:

<ContentControl Content="{Binding YourViewModelProperty}" />
<ListBox ItemsSource="{Binding YourViewModelCollectionProperty}" />
public class ViewFactory
{
    public UIElement Create(object context)
    {
        // Create the view model
        // You can pass in various information by parameters
        // as I do with context (Constructor Injection)
        var viewModel = new ViewModel(context);

        // Create the view and set the view model as data context
        var view = new View { DataContext = viewModel };
        return view;
    }
}

我同意@Sheridan的回答,只想添加另一种使用视图模型实例化视图的方法:您可以使用工厂模式,可能如下所示:

<ContentControl Content="{Binding YourViewModelProperty}" />
<ListBox ItemsSource="{Binding YourViewModelCollectionProperty}" />
public class ViewFactory
{
    public UIElement Create(object context)
    {
        // Create the view model
        // You can pass in various information by parameters
        // as I do with context (Constructor Injection)
        var viewModel = new ViewModel(context);

        // Create the view and set the view model as data context
        var view = new View { DataContext = viewModel };
        return view;
    }
}

您可以从视图模型的方法中调用此工厂,然后将其分配给例如绑定到UI的数据属性。这允许更大的灵活性-但是@Sheridan的解决方案也很好。

我同意@Sheridan的回答,只想添加另一种方法来使用视图模型实例化视图:您可以使用Factory模式,可能如下所示:

<ContentControl Content="{Binding YourViewModelProperty}" />
<ListBox ItemsSource="{Binding YourViewModelCollectionProperty}" />
public class ViewFactory
{
    public UIElement Create(object context)
    {
        // Create the view model
        // You can pass in various information by parameters
        // as I do with context (Constructor Injection)
        var viewModel = new ViewModel(context);

        // Create the view and set the view model as data context
        var view = new View { DataContext = viewModel };
        return view;
    }
}
您可以从视图模型的方法中调用此工厂,然后将其分配给例如绑定到UI的数据属性。这允许更大的灵活性,但是@Sheridan的解决方案也很好

我应该打破MVVM模式吗

请考虑更多地了解这个模式,知道打破它是什么。此模式的主要目的是明确责任,从而获得可测试和可维护的代码。这方面有很多资源,如本问题所示:

无论如何,为了更具体地回答您的问题,您需要的是如何设置DataContext

创建实例化的ViewModel时,以某种方式将其传递到视图中

是的,您知道,如果在视图的构造函数中为dataContext分配viewModel,它可能会工作,但只有当viewModel有责任创建视图时,它才是可接受的,而在很少的情况下,视图才是可接受的。您甚至可以编写类似的内容,从视图外部直接设置DataContext:

var l_window = new MyView { DataContext = new MyViewModel() };
l_window.Show();
[Import]
private MyViewModel ViewModel
{
set { this.DataContext = value; }
get { return this.DataContext as MyViewModel; }
}
当然,该代码的主要缺点是不可测试。如果你想测试它,你应该使用一个可模仿的服务来管理视图的创建

一个更常见的解决方案是向dataContext注入类似prism的IOC容器。您可以在软件启动时创建所有必需的ViewModel,并将它们存储在此IOC容器中。然后,在创建视图时,要求此容器获取viewModel的实例

例如:在PRISM中导出viewModel:

[Export]
public class MyViewModel {...}
然后在视图中导入它:

var l_window = new MyView { DataContext = new MyViewModel() };
l_window.Show();
[Import]
private MyViewModel ViewModel
{
set { this.DataContext = value; }
get { return this.DataContext as MyViewModel; }
}
希望能有帮助

我应该打破MVVM模式吗

请考虑更多地了解这个模式,知道打破它是什么。此模式的主要目的是明确责任,从而获得可测试和可维护的代码。这方面有很多资源,如本问题所示:

无论如何,为了更具体地回答您的问题,您需要的是如何设置DataContext

创建实例化的ViewModel时,以某种方式将其传递到视图中

是的,您知道,如果在视图的构造函数中为dataContext分配一个viewModel,它可以工作,但只有当viewModel有责任创建一个 在非常少的情况下是可以接受的。您甚至可以编写类似的内容,从视图外部直接设置DataContext:

var l_window = new MyView { DataContext = new MyViewModel() };
l_window.Show();
[Import]
private MyViewModel ViewModel
{
set { this.DataContext = value; }
get { return this.DataContext as MyViewModel; }
}
当然,该代码的主要缺点是不可测试。如果你想测试它,你应该使用一个可模仿的服务来管理视图的创建

一个更常见的解决方案是向dataContext注入类似prism的IOC容器。您可以在软件启动时创建所有必需的ViewModel,并将它们存储在此IOC容器中。然后,在创建视图时,要求此容器获取viewModel的实例

例如:在PRISM中导出viewModel:

[Export]
public class MyViewModel {...}
然后在视图中导入它:

var l_window = new MyView { DataContext = new MyViewModel() };
l_window.Show();
[Import]
private MyViewModel ViewModel
{
set { this.DataContext = value; }
get { return this.DataContext as MyViewModel; }
}
希望能有帮助