在过去几周或几个月里,这个问题一直围绕着我,我真的不知道什么是最好的解决方案。
使用MVVM模式,我们使用View Models将数据公开给View。 例如,如果我想向用户显示产品的详细信息,我将在视图模型中创建某些属性并填充它们。然后通过绑定,视图将能够从这些属性中获取数据。像这样:
<StackPanel>
<TextBlock Text="Prodcut Name:" FontWeight="Bold" />
<TextBlock Text="{Binding Path=ProductName}" />
<TextBlock Text="Price:" FontWeight="Bold"/>
<TextBlock Text="{Binding Path=Price}"/>
<TextBlock Text="Added Date:" FontWeight="Bold" />
<TextBlock Text="{Binding Path=Date}"/>
</StackPanel>
在视图模型中,我将检索要显示的数据。我将获得像Product DTO这样的数据,它将在视图中具有所需的属性。
this.productDTO = getData();
所以我的问题是,我们可以将directy从视图模型绑定到dto吗? 查看型号:
private ProductDTO product;
public string ProductName
{
get { return this.product.Name; }
set { this.product.Name = value; }
}
public string Price
{
get { return this.product.Price; }
set { this.product.Price = value; }
}
我认为暴露DTO并不是件好事。 但是如果它将使我不必将所有属性从DTO映射到视图模型..
答案 0 :(得分:5)
如果您不需要“塑造”您的DTO以绑定您的视图,那么将DTO直接暴露给您的视图绝对没有错。如果需要,您可以随时在某个时间点引入视图模型。
您还可以使用mini-ViewModel(I describe on my blog)之类的模式添加本地化的View Models来塑造模型的各个部分。
像您一样在视图模型中包装DTO,添加的代码不会带来任何好处。它增加了代码库的大小和错误的风险。
KISS - 保持简单!
答案 1 :(得分:5)
private ProductDTO product;
public string ProductName
{
get { return this.product.Name; }
set { this.product.Name = value; }
}
我能看到的唯一问题是,当您的dto的Name属性发生更改时,它不会简单地反映在您的UI中。所以我更喜欢这个:
public ProductDTO Product {...}
<TextBlock Text="{Binding Path=Product.Name}" />
这当然要求你的DTO实现INotifyPropertyChanged
答案 2 :(得分:2)
从技术上讲,两种方式都是可能的,但是DTO通常不用于查看,因此可能不会触发任何更改通知事件。您必须在DTO中编写代码或冒可能的UI同步问题。我建议不要以这种方式“丰富”你的DTO。
从架构的角度来看,DTO对象应该是便宜且小的对象。它们不需要花费很多精力来实例化或销毁,你不应该把它们传递到你的调用堆栈很远的地方,更不用说让它们长时间保留在内存中了。一般来说,它们意味着是数据封装,它们的目的只是将数据从A带到B.另一方面,ViewModels具有行为并实现更丰富的接口。他们与DTO的唯一共同点是它们也有数据属性。
因此,在您的情况下,我建议不要将DTO作为私有成员保留在视图模型中,而是在检索DTO时设置视图模型属性,然后再次忘记DTO。作为一般建议,不要让您的DTO的生命周期延长到服务电话的方法之后。