如何将View,ViewModel和DataTemplate捆绑在WPF应用程序中,以方便重用? [英] How to bundle View, ViewModel and DataTemplate in a WPF application for easy reuse?

查看:146
本文介绍了如何将View,ViewModel和DataTemplate捆绑在WPF应用程序中,以方便重用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

情况:



我想创建一个灵活的应用程序,它是ViewModel驱动的。



基本流程是这样的:


  1. 设计主ViewModel

  2. 创建一个UserControl作为视图和一个DataTemplate为主ViewModel选择此视图

  3. 如果有子组件,则由Sub ViewModels建模

  4. 创建一个UserControl作为视图和一个用于选择此视图的子ViewModel的DataTemplate

如果需要显示子视图模型,则通过DataTemplate完成。 / p>

也可以看到这种方法 here < a>(选项8)。



所以主窗口xaml看起来像这样:

 < Window> 
<! - 不知何故,我需要将ViewModel的映射添加到View - >
< Grid>
<! - 主ViewModel - >
< ContentPresenter Content ={Binding Path = Content}/>
< / Grid>
< / Window>

内容属性可能包含视图模型它包含名为 Children 的元素列表,它的关联DataTemplate可能如下所示:
孩子们也可以由适当的DataTemplate灵活渲染。

 < UserControl> 
< Grid>
< StackPanel>
<! - 在列表中显示子ViewModels - >
< ItemsControl ItemsSource ={Binding Path = Children}/>
< / StackPanel>
< / Grid>
< / UserControl>



问题:




  1. 如何组织ViewModels,Views和它们的DataTemplates,所以我不需要在MainWindow中连接它们。


  2. 然后我连接到主窗口?


  3. 如果它是可以存在的,那么我可以在设计时使用dataContext看到结果。


基本上我想捆绑View,ViewModel和DataTemplate,并且能够在不需要知道的应用程序中使用它们细节(例如,一些Sub ViewModel实现了一个特定的接口并被注入到主ViewModel中)。

解决方案

href =http://compositewpf.codeplex.com/ =nofollow>棱镜



该框架允许您定义您的可以注册视图的UI。我相信这回答你的第二个问题(2)。

  xmlns:cal =http://www.codeplex.com/棱镜

< Window>
<! - 不知何故,我需要将ViewModel的映射添加到View - >
< Grid>
<! - 主ViewModel - >
< ContentPresenter cal:RegionManager.RegionName =MainRegion/>
< / Grid>
< / Window>

对于您的第一个问题(1),我们以下列方式构建了我们的实体:



查看 - 我们有一个类似于抽象的基类:

  public abstract class ViewBase< T> :UserControl,IView< T>其中T:IViewModel 
{
public T ViewModel
{
get
{
return this.viewModel;
}
protected set
{
this.viewModel = value;

this.DataContext = this.viewModel;
}
}

public ViewBase(IUnityContainer container)
{
this.ViewModel = container.Resolve< T>();
}
}

这样可以让我们在xaml中使用以下:

 < ui:ViewBase x:Class =MyView
xmlns =http:// schemas
xmlns:ui =NAMESPACE FOR VIEWBASE
xmlns:vm =NAMESPACE FOR VIEWMODEL
xmlns:x =http: //schemas.microsoft.com/winfx/2006/xaml
x:TypeArguments =vm:MYVIEWMODEL>

在View中的代码中,我们执行以下操作:

  public partial class MyView:ViewBase< IMyViewModel> 

然后,使用基类中的构造函数来解析ViewModel并将其设置为DataContext 。



然后,您可以按照预期设计您的视图(3),并且不需要使用DataTemplate。



使用UnityContainer,我们然后注册视图如下:

  this.container.RegisterType< IMyView,MyView> (); 
this.container.RegisterType< IMyViewModel,MyViewModel>();

this.regionManager.RegisterViewWithRegion(MainRegion,typeof(IMyView));

请注意,这里的MainRegion与MainWindow xaml中指定的RegionName匹配。如果您想在同一区域显示多个视图,或者甚至将MainWindow打破到不同的区域,您可以进一步扩展它以使用TabControl。



我希望这有助于。


Situation:

I'd like to create a flexible application which is ViewModel driven.

The basic flow is like this:

  1. Design the main ViewModel
  2. Create a UserControl as View and a DataTemplate for the main ViewModel to select this View
  3. If there are sub components, the are modelled by sub ViewModels
  4. Create a UserControl as View and a DataTemplate for the sub ViewModel to select this View

If a sub view model needs to be presented, it is done via a DataTemplate.

This approach can also be seen here (option 8).

So the main window xaml looks something like this:

<Window>
    <!-- somehow I need to add the mapping from ViewModel to View -->
    <Grid>
        <!-- the main ViewModel -->
        <ContentPresenter Content="{Binding Path=Content}"/>
    </Grid>
</Window>

The Content property might contain a view model that contains a list of elements named Children and it's associated DataTemplate might look like this: The children are also flexibly rendered by a suitable DataTemplate.

<UserControl>
    <Grid>
        <StackPanel>
            <!-- display the child ViewModels  in a list -->
            <ItemsControl ItemsSource="{Binding Path=Children}" />
         </StackPanel>
    </Grid>
</UserControl>

Question:

  1. How should I organize the ViewModels, Views and their DataTemplates so I don't need to hardwire them in the MainWindow?

  2. How do I then connect this to the main window?

  3. It would be nice if it is stub-able, i.e. I can see the result during design time with a design time dataContext.

Basically I want to bundle the View, ViewModel and DataTemplate and be able to use them in an application that doesn't need to know about the details (e.g. some sub ViewModel implements a certain interface and is injected into the main ViewModel).

解决方案

Have you looked into Prism.

The framework allows you to define regions within your UI that views can be registered against. I believe this answers your 2nd question (2).

xmlns:cal="http://www.codeplex.com/prism"

<Window>
   <!-- somehow I need to add the mapping from ViewModel to View -->
   <Grid>
      <!-- the main ViewModel -->
      <ContentPresenter cal:RegionManager.RegionName="MainRegion"/>
   </Grid>
</Window>

For your first question (1) we structure our entities in the following way:

View - we have an abstract base class that looks similar too:

public abstract class ViewBase<T> : UserControl, IView<T> where T: IViewModel
{
    public T ViewModel
    {
        get
        {
            return this.viewModel;
        }
        protected set
        {
            this.viewModel = value;

            this.DataContext = this.viewModel;
        }
    }

    public ViewBase(IUnityContainer container)
    {
        this.ViewModel = container.Resolve<T>();
    }
}

This then allows us to create Views in xaml using the following:

<ui:ViewBase x:Class="MyView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:ui="NAMESPACE FOR VIEWBASE"
         xmlns:vm="NAMESPACE FOR VIEWMODEL"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         x:TypeArguments="vm:MYVIEWMODEL">

In the code behind of a View we do the following:

public partial class MyView : ViewBase<IMyViewModel>

This then makes use of the constructor in the base class to resolve the ViewModel and set it to it's DataContext.

This then allows you to design your view (3) as you intended and also removes the need for having a DataTemplate.

Using the UnityContainer we then register the views as follows:

this.container.RegisterType<IMyView, MyView>();
this.container.RegisterType<IMyViewModel, MyViewModel>();

this.regionManager.RegisterViewWithRegion("MainRegion", typeof(IMyView));

Note that "MainRegion" here matches the RegionName specified in the MainWindow xaml. You can expand this further to use a TabControl if you wanted to display multiple views in the same area, or even break your MainWindow down into different regions.

I hope this helps.

这篇关于如何将View,ViewModel和DataTemplate捆绑在WPF应用程序中,以方便重用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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