在我的应用程序中,我需要一个不同I/O设备的集合,例如串行设备、OPC设备、USB设备等等。我使用了MEF框架来提供一种处理集合和允许添加新设备的方法。
我的项目看起来是这样的:
Atf.Model 'contains the model
Atf.Gui 'the views and view-models
Atf.Devices 'contains implementations of IDevice and exports them许多设备需要配置,因此设备接口向自定义控件和相应的视图模型公开路径,该视图模型处理设备配置的编辑。我试图坚持MVVM模式,并希望尽可能地将视图和模型分开。同时,我希望尽可能地保持与设备集合的耦合。
在Atf.Gui中,我有一个控件,它显示所有已发现的设备,并显示已激活的设备。当一个激活的设备被选中时,我想动态地显示它的编辑器。
我该怎么做?以下是一些(疯狂的)想法:
Idea-1只是在我的视图中加载一个UserControl -模型使用设备对象中的路径。这将打破MVVM的分离,使该部分“不可测试”。
public System.Windows.Controls.UserControl ConfigureControl
{
get
{
// code to load the UserControl using the path property
}
}Idea-2让设备只公开一个视图模型,并使用映射(在设备存储库中定义)来获取视图。不知道该怎么做。
<myeditorcontainer>
<ContainerControl Content="{Binding CurrentlySelectedDeviceViewModel}"/>
</myeditorcontainer>在我看来,Idea-3,使用绑定加载控件。不确定这是否有可能。
<myeditorcontainer>
<UserControl Path="{Binding CurrentlySelectedDeviceViewPath}"
DataContext="{Binding CurrentlySelectedDeviceViewModel}"/>
</myeditorcontainer>发布于 2013-07-10 14:00:36
我认为第二种想法是可行的。
假设ContainerControl是从ContentControl派生的,您应该能够为将要显示的每种类型的视图模型指定一个DataTemplate,然后根据视图模型的类型来呈现正确的UI。例如:
<myeditorcontainer>
<ContainerControl Content="{Binding CurrentlySelectedDeviceViewModel}">
<ContainerControl.Resources>
<DataTemplate DataType="{x:Type ViewModel1Type}">
<!-- controls for ViewModel1's UI -->
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel2Type}">
<!-- controls for ViewModel2's UI -->
</DataTemplate>
</ContainerControl.Resources>
</ContainerControl>
</myeditorcontainer>如果您需要比视图模型的类型更灵活来决定使用哪个模板,则可以指定一个ContentTemplateSelector。它将返回根据您所需的任何条件使用的正确模板。
发布于 2013-07-12 09:06:11
这就是我最后所做的,它似乎运作得很好。其关键特性是,视图模型与视图具有相同的名称,但附加了“Model”,视图模型派生自特定的类-- DeviceSettingsBase。
XAML:
<ContentControl Content="{Binding ConfigControl}"/>视图-模型:
private RequiredDeviceViewModel rdvm;
public ContentControl ConfigControl
{
get
{
// get assembly which contains this object
Assembly assy = Assembly.GetAssembly(rdvm.Device.GetType());
// get View-Type using the name defined in the Device
Type viewType = assy.GetType(rdvm.Device.ConfigureControlResourceName, true);
// get ViewModel-Type using the viewname + Model (may be null)
Type viewModelType = assy.GetType(rdvm.Device.ConfigureControlResourceName + "Model", false);
// instantiate the view control
ContentControl view = (ContentControl)Activator.CreateInstance(viewType);
// instantiate viewModel - if type not null
if (viewModelType != null)
{
object viewModel = (object)Activator.CreateInstance(viewModelType, new object[] { rdvm.RequiredDevice.Config.ConfigString });
view.DataContext = viewModel;
// all device viewModels must derive from DeviceSettingsBase
CurrentConfigViewModel = viewModel as DeviceSettingsBase;
if (CurrentConfigViewModel != null)
{
CurrentConfigViewModel.IsEditable = IsEditable;
CurrentConfigViewModel.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(vmb_PropertyChanged);
CurrentConfigViewModel.SettingsChanged += new SettingsChangedHandler(vmb_SettingsChanged);
}
}
return view;
}
}https://stackoverflow.com/questions/17572499
复制相似问题