2013-07-03 32 views
0

好吧,我正在试图去掌握MVVM。我有一个应用程序有多个图像捕捉选项。根据模式,图像可以从现有文件加载,也可以从相机捕获。为不同ViewModel动态显示不同视图,但属性相同

我正在使用表示图像捕捉设备配置的MVVM模式编写页面。

该模型由两个类组成,这两个类展示了符合IImageSource公共接口的每种模式的特定(和非公用)值。

每两个模型类的具有上下文定义视图模型:

  • CameraSourceViewModel
  • FileSourceViewModel

和两个相应的视图。

  • CameraSourceView
  • FileSourceView

该模型具有它返回IImageSource的属性。

我目前使用第三个视图,ImageSourceView作为页面。我正在处理从模型中获取值的加载事件,然后根据类型将实例化正确的视图模型和正确的视图,然后添加它作为内容。然而,这似乎违背了MVVM的精神,因为我现在已经在代码背后编写了一些决策代码。

是否有更优雅/更好的方式来确定应该实例化和使用哪个视图模型/视图?

回答

1

其实,你不应该需要一个TemplateSelector,因为两者的ViewModels都会有不同的类型。您可以在XAML中声明的DataTemplates与模型类型作为重要资源,使WPF自动选择正确的DataTemplate:

  • 有一个主视图模型,它公开了一个ImageSourceViewModel属性。该属性将根据需要返回CameraSourceViewModel或FileSourceViewModel。
  • 在您的网页,在DataContext将是主视图模型,你不得不XAML这样的:

代码示例:

<Page x:Class="Page1" 
    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:my="clr-namespace:WpfApplication1" 
    mc:Ignorable="d" 
    d:DesignHeight="300" d:DesignWidth="300" 
    Title="Page1"> 
<Page.Resources> 
    <DataTemplate DataType="{x:Type my:CameraSourceViewModel}"> 
     <my:CameraSourceView/> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type my:FileSourceViewModel}"> 
     <my:FileSourceView/> 
    </DataTemplate> 
</Page.Resources> 
<Grid> 
    <ContentControl Content="{Binding ImageSourceViewModel}"/> 
</Grid> 
</Page> 
+0

对不起,花了这么长时间来标记你的答案,在项目的另一部分被误解了,只是需要回来。 –

1

你有你需要决定在运行时使用的两个型palces:

  1. 视图模型
  2. 查看

在视图模型级只是使用视图模型工厂,所以才由事件类型/ ValueType实例化适当的ViewModel:

private IImageSourceViewModel ProcessEvent(IEvent someEvent) 
{ 
    return viewModelFactory.Create(someEvent.Type) 
} 

然后在视图水平只使用DataTemplateSelector其通过结合已经解决视图模型实例接受,然后决定使用哪个搜索:

的MainView XAML:

<ContentControl 
    Content="{Binding ImageSourceViewModel}"  
    ContentTemplateSelector = 
     "{StaticResource ImageSourceViewDataTemplateSelector}"> 
</ContentControl> 

ImageSourceViewDataTemplateSelector:

private sealed class ImageSourceViewDataTemplateSelector: DataTemplateSelector 
{ 
    public ImageSourceViewDataTemplateSelector(... dependencies if any...) 
    {    
    } 
    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     DataTemplate dataTemplate = null; 
     IImageSourceViewModel instance = item as IImageSourceViewModel; 

     // move out into the constructor 
     var dataTemplateFactory = new Dictionary<Type, Func<DataTemplate>> 
      { 
        { typeof(ICameraSourceViewModel), (x) => this.Resources["CameraSourceDataTemplate"] as DataTemplate }, 
        { typeof(IFileSourceViewModel), (x) => this.Resources["FileSourceViewModel"] as DataTemplate } 
      }; 

     // TODO: handle not supported type case yourself 

     return dataTemplateFactory[instance.GetType()](); 
    } 
} 
+0

我已经做了我最好的破译它是什么你试图在这里展示我,但我失败了。我在字典中遇到了一些问题, IFilter的作用是什么,为什么你不在最后一行中传递价值? –

+0

对不起,忘记了解除这一点,请查看最新答案 – sll

1

下面是关于一些想法你可以做什么:

ImageSourceViewModel,这是您的ImageSourceView视图的ViewModel。这个视图模型的作用是从模型中获得“您的价值”,并将其作为IImageSource类型的公共属性公开。

然后,在你ImageSourceView视图,你可以使用一个模板选择更改视图的内容,这取决于具体类型暴露IImageSource财产。

http://www.codeproject.com/Articles/418250/WPF-Based-Dynamic-DataTemplateSelector

相关问题