0

私のアプリケーションでは、シリアル、OPC、USB デバイスなどのさまざまな I/O デバイスのコレクションが必要です。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は、検出されたすべてのデバイスを表示し、アクティブ化されたデバイスを表示するコントロールがあります。アクティブ化されたデバイスが選択されたときに、そのエディターを動的に表示したいと考えています。

どうすればこれを行うことができますか? ここにいくつかの(クレイジーな)アイデアがあります:

アイデア-1UserControlデバイス オブジェクトのパスを使用して、ビュー モデルにa をロードするだけです。これにより、MVVM の分離が壊れ、その部分が「テスト不能」になります。

public System.Windows.Controls.UserControl ConfigureControl 
{
   get 
   {
       // code to load the UserControl using the path property
   }
}

アイデア 2デバイスでビュー モデルのみを公開し、マッピング (デバイス リポジトリで定義) を使用してビューを取得します。これがどのように行われるかわかりません。

<myeditorcontainer>
    <ContainerControl Content="{Binding CurrentlySelectedDeviceViewModel}"/>
</myeditorcontainer>

アイデア 3私の見解では、バインディングを使用してコントロールをロードします。これがまったく可能かどうかはわかりません。

<myeditorcontainer>
    <UserControl Path="{Binding CurrentlySelectedDeviceViewPath}" 
                 DataContext="{Binding CurrentlySelectedDeviceViewModel}"/>
</myeditorcontainer>
4

2 に答える 2

1

アイデア 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>

使用するテンプレートを決定するためにビュー モデルのタイプよりも柔軟性が必要な場合は、ContentTemplateSelectorを指定できます。必要な基準に基づいて、使用する正しいテンプレートが返されます。

于 2013-07-10T14:00:36.360 に答える
0

これは私が最終的にやったことであり、うまくいくようです。主な特徴は、ビュー モデルがビューと同じ名前で「モデル」が追加されていること、およびビュー モデルが特定のクラス (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;
    }
}
于 2013-07-12T09:06:11.917 に答える