如何使用相同的viewmodel支持多个视图?

时间:2014-09-12 04:51:33

标签: wpf xaml mvvm user-controls itemscontrol

使用相同视图模型支持多个视图的最佳方式是什么?

(是的......我已阅读" MVVM(使用WPF) - 将多个视图绑定到SameViewModel",但如果我正确读取它,答案涉及创建不同的视图模型,这不是我想要的在这里)。

在下面的代码中,当InkStringView由定义的行组成时,StringViewModel支持InkStringView。我现在希望定义一个由列组成的第二个视图,但必须保留StringViewModel的相同的 datacontext。在第二个视图中,控件具有不同的位置和大小,StringViewModel 计算但其功能和用途保持不变。如果在字符串中创建StringViewModel的模块(一个observablecollection)不知道将使用哪个视图而将最终决策留给usercontrol的xaml,那将是理想的。

我的问题是如何设计StringViewModel和/或DataTemplate以通过仅更改DataTemplate来允许基于该视图的不同视图和计算。

(我尝试将StringViewModel继承到不同的viewmodel,每个viewmodel特定于其视图,但它不起作用)。

提前感谢您的任何帮助或建议。或者他们是更好的方式?

示例:

<DataTemplate DataType="{x:Type vm:StringViewModel}">
               <v:InkStringView_2 />          <----CHANGING THE VIEW TO COLUMNS. ViewModel needs
</DataTemplate>                                    to perform calculations specific to the view.

用户控件是:

<UserControl.Resources>
       <DataTemplate DataType="{x:Type vm:StringViewModel}">
               <v:InkStringView />
       </DataTemplate>
   </UserControl.Resources>

<Grid>
     <ItemsControl 
        ItemsSource="{Binding Strings}" >
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Control.Margin" Value="{Binding Margin}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>      
</Grid>
</UserControl>

3 个答案:

答案 0 :(得分:1)

只是一个建议:

你有一个viewmodel MyViewmodel,你想用不同的DataTemplates显示它。那么对我来说,一个简单的方法就是创造&#34; new&#34;带有&#34; no&#34;的课程实施

 public class MyT1 : MyViewmodel {}
 public class MyT2 : MyViewmodel {}
 public class MyT3 : MyViewmodel {}

所以现在所有的MyT1,MyT2,MyT3都有相同的方法和内容,但是你可以创建一个数据模板来预测它们

   <DataTemplate DataType="{x:Type vm:MyT1}">
           <v:T1View />
   </DataTemplate>
   <DataTemplate DataType="{x:Type vm:MyT2}">
           <v:T2View />
   </DataTemplate>
   <DataTemplate DataType="{x:Type vm:MyT3}">
           <v:T3View />
   </DataTemplate>

或者您不使用Viewmodel First方法并执行View First,然后您可以使用Datacontext选择所需的视图

答案 1 :(得分:1)

我遇到了类似的问题,我解决问题的方法是使用ControlTemplate所以:
在您的视图中:

<Control>
    <Control.Resources>
         <Style TargetType="Control">
              <Setter Property="Template">
                   <Setter.Value>
                        <ControlTemplate TargetType="Control">
                              <!-- Here you put you view it could be a UC if you want -->      
                         </ControlTemplate>
                   </Setter.Value>
              </Setter>
         </Style
    </Control.Resources>
</Control>  

然后在您的Style.Resources中,您可以定义TriggersDataTriggers来更改控件的Template属性。这样就可以保持ViewModel不变,只需更改获取数据的Views即可。希望这是有道理的,如果有什么事情让我们大喊大叫,我会把更多的信息放进去 HTH

答案 2 :(得分:0)

不是答案,而是一个简单的解决方案。

重新定义字符串,ItemsSource,

ObservableCollection<StringViewModelBase> Strings

然后将StringViewModelBase的子项创建为

public class StringByRowViewModel : StringViewModelBase

然后将资源中的DataTemplate更改为

  <DataTemplate DataType="{x:Type vm:StringByRowViewModel}">
        <v:InkStringByRowView />
  </DataTemplate>
  <DataTemplate DataType="{x:Type vm:StringByColumnViewModel}" >
        <v:InkStringByColumnView />
  </DataTemplate>

最后,我认为别无选择,只能更改构建字符串的模块(至少就视图模型而言)。而不是

 StringViewModelBase svm = new StringViewModelBase(text,color, w);  

使用

 StringByColumnViewModel svm = new StringByColumnViewModel(text,color,w);

   Strings.Add(svm);

显然,ObservableCollection只需要一个共同的父级,并且数据类型仍然保留在XAML中。