我有一个服务返回一个Party类型的数组。党有两个子类型,人和组织。我正在使用视图模型在我的WPF应用程序(Prism,MVVM)中使用此服务。在此视图模型的构造函数中,我填充了Party类型的可观察集合:
public PhoneBookViewModel(IPhoneBookService phoneBookProxy)
{
_phoneBookProxy = phoneBookProxy;
var parties = _phoneBookProxy.GetAllParties();
_parties = new ObservableCollection<Party>(parties.ToList());
}
到目前为止一切顺利。在我的PhoneBookView中,我有一个绑定到此集合的ItemsControl。在此控件中,我想使用另一个View(及其视图模型)渲染每个Party。所以当Party是Person类型时,注入PersonView并将Party对象传递给PersonViewModel的构造函数,当Party类型为Organization时,渲染OrganizationView,等等......你得到图片(或?)。
但我无法弄清楚如何在XAML中执行此操作。有任何想法吗? 这可能不是最好的方法,所以如果你能推荐一个更好的方法,请赐教: - )
谢谢!
答案 0 :(得分:1)
让我们从模型的角度来看待这个:
假设我们有2种不同类型的视图,1种视图模型:
ViewA - &gt;使用DataTempate / DataTemplateSelector在Bin控件中创建,Binded&gt;到ViewModelA
ViewB - &gt;使用DataTempate / DataTemplateSelector在一个项目控件中创建,Binded到ViewModelA
如果两个视图绑定到同一视图模型,您最终会得到相同的视图。
让我们再尝试两种不同类型的视图和两种不同类型的视图模型:
ViewA - &gt;使用DataTempate / DataTemplateSelector在一个项目控件中创建,Binded到ViewModelA - &gt;绑定到ModelA
ViewB - &gt;使用DataTempate / DataTemplateSelector在项目控件中创建,Binded到ViewModelB - &gt;绑定到ModelB
这是可能的。
现在,如果您对这种视图模型和模型进行建模(伪代码):
public PhoneBookViewModel
{
public PhoneBookViewModel()
{
_parties = new ObservalbeCollection<PartyViewModel>();
}
private PhoneBook _dataContext;
// This is the property the VM uses to access the model
public PhoneBook DataContext
{
get { return _dataContext; }
set
{
if (_dataContext != null)
{
_dataContext.Parties.CollectionChanged -= OnModelPartiesChanged;
}
_dataContext = value;
if (_dataContext != null)
{
_dataContext.Parties.CollectionChanged += OnModelPartiesChanged;
}
}
}
private ObservableCollection<PartyViewModel> _parties;
// This is the property the view uses to access the collection of VM parties
public ObservableCollection<PartyViewModel> PartiesViewModels { get { return _parties; } }
private void OnModelPartiesChanged(...)
{
// Add/remove VMs to/from PartiesViewModels here
}
}
// Model
public PhoneBook
{
public PhoneBook()
{
_parties = new ObservalbeCollection<Party>();
}
private ObservableCollection<Party> _parties;
// This is the property the VM uses to access the model's parties
public ObservableCollection<Party> Parties { get { return _parties; } }
}
public PersonViewModel : PartyViewModel
{
new Person DataContext { get; set; }
}
public PartyViewModel
{
public Party DataContext { get; set; }
}
然后您将获得每个模型项的正确类型的VM, 视图将绑定到VM项目,而不是模型项目。
查看数据表:
<DataTemplate x:Target={x:Type myVmNamespace:PersonViewModel}">
<PersonView/>
</DataTemplate>
<DataTemplate x:Target={x:Type myVmNamespace:GroupViewModel}">
<GroupView/>
</DataTemplate>
查看的itemscontrol:
<!-- Bind to Parties property of PhoneBookVM -->
<!-- Uses datatemplates for items -->
<ListView ItemsSource={Binding Parties}"/>
答案 1 :(得分:0)
为数据类型配置数据模板以呈现xaml。
答案 2 :(得分:0)
如果您正在使用Prism和MVVM,那么您将命令绑定到与所有缔约方的ItemsControl。
此命令的类型为DelegateCommand<Party>
。在执行命令的Delegate内部,如下所示:
private void PartyNavigate(Party party)
只需检查该方是否属于任何子类型,并在RequestNavigate
的区域内拨打RegionManager
特定视图。
如果您传递实际上下文将成为一个问题,您可以查看Prism附带的MVVM RI,它以StateHandler
的形式对此非常好,或者你可以构建您自己的集中式DataManager,您可以在其中保存这些内容的状态,以及从WebServices获取的缓存等。使用WPF和WCF构建智能客户端2年后,我可以告诉您最终需要构建自己的DataManager如果您已经在使用EntityFramework并且从EDM中生成了大部分内容,那么这将不是什么大不了的事。
答案 3 :(得分:0)
您的ItemsControl ItemsSource的集合由PhoneBookViewModel填充。因此,唯一剩下的就是告诉WPF应该如何呈现此集合的每个项目。这可以通过创建DataTemplate轻松实现。
<DataTemplate DataType="{x:Type PersonViewModel}">
<MyPersonView/>
</DataTemplate>