MVVM数据模板和非直接数据映射

时间:2011-08-30 12:59:21

标签: xaml silverlight-4.0 mvvm

我一直在使用mvvm来开发一个RIA服务sl4应用程序,我似乎错过了一些东西。

当您的数据以预期的编辑格式或数据对象“适合视图”(网格,列表等)时,MVVM和数据绑定很有用。但是当你的数据没有直接映射时会发生什么?

我的例子

假设我有一个产品表,这定义了产品的价格和选项。我有一个订阅的产品表,它将链接产品和客户端,并且还有关于订阅何时结束的数据......

所以,当我开始研究“购物清单”时,我就这样做了:

    <ListBox x:Name="ShopList" Grid.Row="0" ItemsSource="{Binding Products}">
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <sdk:Label Content="{Binding ModuleName}" />
                <sdk:Label Content="{Binding DateStart, Converter={StaticResource gridDateFormatter}}" />
                <sdk:Label Content="{Binding DateEnd, Converter={StaticResource gridDateFormatter}}" />
                <telerik:RadMaskedTextBox MaskedText="{Binding UnitsToBuy}" />
                <sdk:Label Content="{Binding UnitStep}" />
                <sdk:Label Content="{Binding TotalPrice}" />
            </StackPanel>
        </DataTemplate>
    </ListBox>

所以我认为我会在我的ViewModel上将ItemsSource与Observable集合绑定

public ObservableCollection<Product> Products

但是现在我遇到了问题,UnitsToBuy不属于产品,不属于产品。我很想知道如何找到一种干净的方式来处理这些情况。假设我可以在该列表中包含任意数量的项目。

感谢。

3 个答案:

答案 0 :(得分:3)

我认为你所要求的归结为视图需要具有更多属性的视图模型,而不是简单的模型。为什么不这样的东西。显然,下面的类应该实现INotifyPropertyChanged。

public class CartItem
{
  public Product Product {get;set;}
  public int UnitsToBuy {get;set;}
  public int UnitsStep {get;set;}
  public decimal TotalPrice
  {
    get { return Product.Price * UnitsToBuy;}
  }
  //more properties can be added if needed
}

public class ShoppingCartViewModel
{
  public ObservableCollection<CartItem> Products {get;set;}
}

然后在xaml中你真的不需要做任何改变。

答案 1 :(得分:0)

我将创建一个新的Model类,它将包含Product和SubscribedProduct所需的内容。然后,您可以创建一个类别的Mapper,将更多以视图为中心的模型转换为以数据为中心的模型(Product and SubscribedProduct)。

答案 2 :(得分:0)

我总是专门为模型或模型组构建我的视图。因此,我知道期望什么属性,以及可能缺少哪些属性。

如果我知道某个属性可能丢失,我会写一个DataTrigger来根据数据改变视图

例如,如果我有一个应该显示ProductsSubscribedProducts的视图,我可能会使用DataTrigger来确定要显示的DataTemplate

<Style TargetType="ListBoxItem">
    <Setter Property="Template" Value="{StaticResource DefaultProductTemplate}" />
    <Style.Triggers>
        <DataTrigger Binding="{Binding Converter={StaticResource ObjectToTypeConverter}}" Value="{x:Type local:SubscribedProductModel}">
            <Setter Property="Template" Value="{StaticResource SubscribedProductTemplate}" />
        </DataTrigger>
    </Style.Triggers>
</Style>