0

2つの子ビューがあるリストビューがあります。1つは表示ビューで、もう1つは編集ビューです。これが私がリスト(親)ビューを定義した方法です。2つの子UserControlが親の異なるスペースを占めるようにしたいことに注意してください。

<UserControl x:Class="RelayAnalysis_UI.Views.Relays.RelayListView"
    ....

    <ContentControl x:Name="GroupDetail" Grid.Row="2" />
    <TabControl x:Name="Items" Grid.Column="0" Style="{StaticResource TabControlStyle}" Margin="5,0,0,0"/>
</UserControl>

次に、私のビューモデルでは、次の方法でユーザーの応答に基づいてこれらのアイテムをアクティブ化します

**モデルを表示**

[Export(typeof(RelayListViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class RelayListViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<Group> {
    ....
    public void Edit() { //Requested Edit
        RelayEditViewModel viewModel = TryAndLocateViewModel(SelectedRelay.Group.Rack.Id, SelectedRelay.Group.Id);
        ActivateItem(viewModel);
    }
    ....

    public void ViewGroupDetail(Relay relay) { //Requested View
        GroupDetailViewModel viewModel = container.GetExportedValue<GroupDetailViewModel>();
        ActivateItem(viewModel);
    }

上記のコードは機能しますが、詳細ビューはタブスペース(編集ビュー用のスペース)に読み込まれます。実際には、ActivateItem(viewModel)は表示する正しいタイプのビューを選択しますが、表示ビューの間違った場所にロードされます。つまり、表示ビューは画面上の編集ビューのスペースにロードされます。確かに私はいくつかの明白なものを逃しています。

要約すると、親UserControlで定義された2つのUserControlを取得して、独自のスペースでアクティブ化するにはどうすればよいですか?

編集-1:

これは、編集ビューと詳細ビューをそれぞれロードする必要がある場所を示す2つのスクリーンショットです。

ロードされた画面の編集

ロードされた画面の表示(編集領域にロードされるべきではありません)

2番目のスクリーンショットでわかるように、詳細ビューは詳細領域と編集領域(タブ)に読み込まれます。詳細ビューだけを詳細領域に表示したくありません。編集領域は編集ビュー専用です。

これが、スクリーンショットを生成するために使用したコードです。

両方のビューを収容するメインビュー

<UserControl x:Class="RelayAnalysis_UI.Views.Relays.RelayListView"
    <Grid>
         ....
                     <ContentControl x:Name="GroupDetail" HorizontalContentAlignment="Left" 
                                        cal:View.Context="GroupDetail" cal:View.Model="{Binding ActiveItem}"/>
                    <TabControl x:Name="Items" Grid.Column="0" Style="{StaticResource TabControlStyle}" Margin="5,0,0,0"
                                cal:View.Context="RelayEdit" cal:View.Model="{Binding ActiveItem}"/>
     </Grid>
</UserControl>

編集2: 私はそれを機能させるのに非常に近いと思います。あなたの提案に従って、私はMain(Parent)コンテナを以下のように変更しました。

<UserControl x:Class="RelayAnalysis_UI.Views.Relays.RelayListView"
            <ContentControl x:Name="GroupDetail" HorizontalContentAlignment="Left" />
                <TabControl x:Name="Items" Grid.Column="0" Style="{StaticResource TabControlStyle}" Margin="5,0,0,0" />

編集画面と詳細画面が適切な場所に表示されるようになりました。ただし、Detail ViewModels OnActivateは呼び出されないため、変数が入力されていない空白の詳細ビューが表示されます。詳細ビューフィールドのすべてのロードは、OnActivate()オーバーライドで実行されます。GroupDetailViewModelの定義方法は次のとおりです

[Export(typeof(GroupDetailViewModel))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class GroupDetailViewModel : Screen {
    ...
    protected override void OnActivate() {
        base.OnActivate();
    ..
    } 

確かに、私はいくつかの属性を失っています。または、詳細を手動でロードするためにGroupDetailViewModelのメソッドを呼び出す必要がありますか?

4

1 に答える 1

1

長くてあまり役に立たなかったため、元の回答を削除しました

編集:

上記を無視してください。2つの異なるビューモデルに2つの異なるビューをロードしようとしているようですが、私が知る限り、これContextは設計されたものではありません。プロパティは、同じビューモデルに対して2つの異なるビューをロードします(Context例:XAML)。

<ContentControl x:Name="GroupDetail" HorizontalContentAlignment="Left" 
    cal:View.Context="GroupDetail" 
    cal:View.Model="{Binding ActiveItem}"/>
<TabControl x:Name="Items" Grid.Column="0" Style="{StaticResource  TabControlStyle}" Margin="5,0,0,0" 
    cal:View.Context="RelayEdit" 
    cal:View.Model="{Binding ActiveItem}"/>

RelayEditViewModelCMを介してアクティブ化された名前のVMを指定するとActivateItem()、次のビューをロードしようとします。

RelayEdit.GroupDetailコンテンツコントロール用

RelayEdit.RelayEditタブコントロール用

見る:

http://caliburnmicro.codeplex.com/wikipage?title=View%2fViewModel%20Naming%20Conventions&referringTitle=Documentation

..。

別のViewModelを読み込もうとすると、同じ規則がビューの検索に適用されます

GroupDetailViewModel結果は

GroupDetail.GroupDetailコンテンツコントロール用

GroupDetail.RelayEditタブコントロール用

これはあなたが望んでいるものではないようです(そして、なぜ何かがロードされているのかわかりません-あなたのビューはどの名前空間にありますか?ビューロケーターをカスタマイズしましたか?)

私はまだあなたが必要とするライフサイクルサポートに頭を悩ませようとしていますが、編集ビューをライフサイクル管理したいようです(ロード/保存/ガードタイプのサポートが必要なため)が、詳細ビューを読む必要があります-保護されていない状態で閉じられてもかまいません

その場合、詳細ビューモデルへの参照を保持するプロパティをViewModelに追加する必要がありますが、アクティブ化しないでください...呼び出しずにプロパティを設定するだけですActivateItem(vm)

例:

[Export(typeof(RelayListViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class RelayListViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<Group> {
....
// Backing field + prop to hold the details view - the content control will bind to this
private IScreen _details;
public IViewAware Details { get { } set { } } // Implement standard NotifyOfPropertyChange here for this property

public void Edit() { //Requested Edit
    RelayEditViewModel viewModel = TryAndLocateViewModel(SelectedRelay.Group.Rack.Id, SelectedRelay.Group.Id);
    ActivateItem(viewModel);
}
....

public void ViewGroupDetail(Relay relay) { //Requested View
    GroupDetailViewModel viewModel = container.GetExportedValue<GroupDetailViewModel>();
    // Instead of activating, just assign the VM to the property and make sure Details calls NotifyOfPropertyChange to let CM know to start the binding logic
    Details = viewModel;
}

次に、XAMLで

<!-- Just bind the details view to the Details property -->
<ContentControl x:Name="Details" HorizontalContentAlignment="Left" /> 
<!-- Leave this as-is, as it's working ok -->
<TabControl x:Name="Items" Grid.Column="0" Style="{StaticResource  TabControlStyle}" Margin="5,0,0,0" /> 

(上記のデフォルトの規則を使用していると想定していますが、必要にTabControl応じて微調整してください)

プロパティを適切に設定する限り、詳細ビューと編集ビューの両方に同じVMを使用できますContext

それが役立つかどうか教えてください

編集:

MVVMやカップリングなどに関する質問に答えるだけです...

あなたがしているのは、いくつかのより単純なビューモデルからより複雑なビューモデルを作成することです(したがって、いくつかのより単純なビューからのより複雑なビュー)。詳細VMへの参照が具体的なタイプでない限り、VM間の結合は非常に緩くなります。そのインターフェイスを実装する任意のビューモデルタイプをメインVMのプロパティに割り当てることができDetail、CMはそのビューを見つけてインターフェイスを構築しようとします。これはまったく問題ありません(必要に応じて、IoCを使用して詳細ウィンドウのタイプを取得できます)

詳細ビューにライフサイクルが必要な場合は、から継承する必要がありますがScreen、詳細ビューをアクティブ化する必要があるとは思えません(詳細ビューであり、準備ができているだけなので)。実装IViewAwareして継承するだけで十分PropertyChangedBaseです。ただし、編集ビューにはライフサイクルが必要であるため、Screen.

ConductorすでにActiveItemプロパティが含まれており、を介してアクティブ化された子アイテムのライフサイクルの管理を提供しActivateItem()ます。実行しているのは、追加のvmを参照するコンダクター用の追加の「ボルトオン」プロパティを作成することだけです(つまり、必要でありActiveItemDetails

于 2012-11-30T11:10:06.760 に答える