WPF DataTemplate / DataTemplateSelector - 2 个不同视图使用 ViewModel 的最佳方法?
基本上,我有以下场景:
ViewModel:FooViewModel:BaseViewModel
,BarViewModel:BaseViewModel
视图:MainView
、FooView
、BarView
现在,我“注入”视图并使用 DataTemplate
和 DataTemplateSelector
设置 DataContext
。显然,我的 ItemsControl
ItemSource
绑定到 ObservableCollection
,其中它(目前)包含 FooViewModel 的实例
和一个 BarViewModel
问题是我想引入一个 AlternateFooView
,我想利用相同的 FooViewModel
。我想我将创建另一个 DataTemplate
并让我的 DataTemplateSelector
返回它,但是需要特殊的逻辑来确定要返回哪个 DataTemplate (我不能仅仅通过其中 ViewModel 在那里),这意味着我必须在 BaseViewModel 中拥有某种类型的属性或字段。我不知道这是否真的是一个好主意,因为这似乎在 ViewModel 中引入了一个仅用于选择视图的字段/属性。它不会损害我的单元测试,但包含一个字段只是为了帮助决定选择哪个 UI 视图似乎是一种浪费。我不认为它破坏了 MVVM,但我很好奇是否有人有其他更好的想法?我的替代想法我更不喜欢......
想法#2:
- 将 FooViewModel 转换为 2 个不同 FooViewModel 扩展的基类(即 BaseFooViewModel、FooViewModel、DifferentFooViewModel)。这看起来很愚蠢,因为除了类类型之外,FooViewModel 和 DifferentFooViewModel 之间实际上没有任何区别。
想法#3:
- 只需复制 FooViewModel 并将其设为 FooViewModel2(它将与 FooViewModel 完全相同)。这似乎比想法#2 更糟糕。
Sample-Code (Adjusted obviously):
public abstract class BaseViewModel : NotificationObject
{
//Common Stuff
}
public abstract MainViewModel : NotificationObject
{
public MainViewModel()
{
MyItems = new ObservableCollection<BaseViewModel>()
{
new FooViewModel();
new BarViewModel();
new FooViewModel(); //New Item -- I want it to use the DifferentFooView
}
//Load items from a DAL later
}
public ObservableCollection<BaseViewModel> MyItems { get; set; }
//Other Stuff
}
<l:MyItemsControl ItemSource={Binding MyItems} ContentTemplateSelector={StaticResource MyTemplateSelector} />
Thanks!
Basically, I have the following scenario:
ViewModel: FooViewModel : BaseViewModel
, BarViewModel : BaseViewModel
Views: MainView
, FooView
, BarView
Right now I "inject" the view and set the DataContext
using DataTemplate
and DataTemplateSelector
. Obviously, my ItemsControl
ItemSource
is bound to an ObservableCollection<BaseViewModel>
in which it contains (for now) an instance of a FooViewModel
and a BarViewModel
The problem is I want to introduce a AlternateFooView
which I want to utilize the same FooViewModel
. I figure I'll create another DataTemplate
and have my DataTemplateSelector
return it, but there needs to be special logic to determine which DataTemplate to return (I can't just go by which ViewModel is there), and that means I'll have to have some type of property or field in the BaseViewModel. I don't know if that's really a good idea because that seems to be introducing a field/property into the ViewModel that is only used to select a view. It won't hurt my unit testing, but it seems like a waste to include a field just to help decide which UI View to choose. I don't think it breaks MVVM, but I'm curious if anyone out there has any other better ideas? The alternative ideas I had I dislike even more...
Idea #2:
- Turn FooViewModel into a base class that 2 different FooViewModel's extend (i.e. BaseFooViewModel, FooViewModel, DifferentFooViewModel). This seems stupid because there really isn't any difference between FooViewModel and DifferentFooViewModel aside from their class type.
Idea #3:
- Just copy FooViewModel and make it FooViewModel2 (it'll be exactly identical to FooViewModel). This seems even worse than idea #2.
Sample-Code (Adjusted obviously):
public abstract class BaseViewModel : NotificationObject
{
//Common Stuff
}
public abstract MainViewModel : NotificationObject
{
public MainViewModel()
{
MyItems = new ObservableCollection<BaseViewModel>()
{
new FooViewModel();
new BarViewModel();
new FooViewModel(); //New Item -- I want it to use the DifferentFooView
}
//Load items from a DAL later
}
public ObservableCollection<BaseViewModel> MyItems { get; set; }
//Other Stuff
}
<l:MyItemsControl ItemSource={Binding MyItems} ContentTemplateSelector={StaticResource MyTemplateSelector} />
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我同意 krishnaaditya 的观点,即问题实际上归结为根据 ViewModel 的状态决定使用哪个视图。这种类型的逻辑通常被放入模板选择器中,效果很好。如果您不想将该逻辑放入模板选择器中,请考虑使用我的 将其外部化路由模板选择方法。这使得通过使用路由事件来委托模板选择逻辑变得容易。
您在评论中提出的关于使用 DataTrigger 的想法也可以工作,但这重新引入了对 VM 对象上的属性的需求,该属性指示要加载哪个视图(您说您不想要)。在我看来,这不一定是坏事。
I agree with krishnaaditya that the question really boils down to what determines which View to use based on the state of the ViewModel. This type of logic is often placed into a template selector, which works great. If you don't want to put that logic into the template selector, consider externalizing it by using my Routed Template Selection approach. That makes it easy to delegate the template selection logic by using a routed event.
The idea you proposed in your comment about using a DataTrigger could also work, but that reintroduces the need for a property on the VM object that indicates which View to load (which you said you don't want). In my opinion, that's not necessarily a bad thing.