Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 是否可以使用绑定按名称加载控件?_Wpf_Binding_Controls - Fatal编程技术网

Wpf 是否可以使用绑定按名称加载控件?

Wpf 是否可以使用绑定按名称加载控件?,wpf,binding,controls,Wpf,Binding,Controls,在我的应用程序中,我需要不同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 许多设备都需要配置,因此设备接口公开了自定义控件的路

在我的应用程序中,我需要不同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>

我认为想法2是一个不错的选择

假设
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>


如果您需要比视图模型的类型更大的灵活性来决定使用哪个样板,则可以指定一个。它将根据您想要的任何标准返回正确的模板以供使用。

这就是我最后所做的,它似乎工作正常。关键特性是视图模型与视图具有相同的名称,但附加了“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;
    }
}