0

メインビューがデータテンプレートを使用してビューを切り替える戦略を定義しています。現在、3つのビューを切り替えることができます。

  • ApplicationView:実際には、多くの異なるビューで構成されるビューであり、ほとんどの場合、タブ/ドッキングを使用して階層化されています。これは、アプリケーションデータを扱うビューです。
  • LogInView:ユーザーのログインに使用されます。
  • DialogView:ダイアログビューを表示するために使用されます。このビューは、データテンプレートを使用して、必要な適切なビューを選択します。

ダイアログビューを表示する必要がある場合は、メインビューの現在のビューとして設定するという考え方です。選択が完了すると、この情報はApplicationViewまたはApplicationViewの一部であるビューに渡されます。DialogViewが表示されている間、ApplicationViewはメモリから解放されないようにする必要があります。これは、ApplicationViewModelが引き続きデータを操作するためです(常にバックグラウンドで動作する必要があります)。

DataTemplatesを使用してこれを実現し、ContentControlのコンテンツをCurrentViewにバインドすることを考えています。

// in MainView
DataTemplate DataType="{x:Type vm:ApplicationViewModel}">
    <vw:ApplicationView />
</DataTemplate>

.....

// in MainViewModel
public ViewModelBase CurrentView { get; set; }

基本的に、ダイアログにモーダルウィンドウを使用しないようにしています。

1)この戦略は大丈夫ですか、それとも私が気付いていない問題がいくつかありますか?

2)DialogViewに切り替えると(実際にはビューモデルを切り替えています)、ApplicationView / ApplicationViewModelはどうなりますか?ApplicationViewModelの参照をどこかに保存して、ガベージコレクションが行われないようにする必要がありますか?これはテストしていませんが、CurrentViewを設定すると、ViewModel/Viewの新しいインスタンスが作成される可能性があります。

3)2番目の質問に関連して、DataTemplatesを使用すると、以前に使用されていたView / ViewModelはどうなりますか?現在は別のview / viewmodelに置き換えられていますか?

4

2 に答える 2

0
  1. 通常、ダイアログを表示しているときにアプリケーションを削除したくない場合でも、ビューを切り替える方法に問題はありません。

    私が過去に行ったことはCurrentView、 と の両方DialogViewを aGridに配置して、それらが互いの上に配置されるようにし、とプロパティをApplicationViewModel含むようにし、ダイアログを表示したいときに、これら 2 つのフィールドに入力するだけです。(例については以下を参照)IDialogViewModelIsDialogVisible

  2. ApplicationViewModel戻って新しいものを作成したくない場合は、どこかに保存する必要がありますApplicationViewModel

  3. WPF は表示されなくなった UI オブジェクトを破棄するため、CurrentViewを からLoginに切り替えるApplicationと が削除され、 がLoginView作成されます。ApplicationView

    ContentControl の Content が yourViewModelに設定されているため、ViewModel は実際には applications に配置されていますVisualTree。WPF がVisualTree描画方法がわからないオブジェクトに遭遇するたびに、オブジェクトのTextBlockを含む を使用して描画.ToString()します。を定義することによりDataTemplate、既定のメソッドを使用する代わりに、オブジェクトを描画する方法を WPF に伝えます.ToString()。オブジェクトが を離れると、VisualTreeオブジェクトをレンダリングするために作成されたビジュアル オブジェクトは破棄されます。

ビューを切り替えるために現在持っているものを引き続き使用しますが、LoginApplication、およびDialogビューにはその方法を使用しません。

通常、LoginViewはログイン時に 1 回だけ表示されますが、Dialogログイン後にユーザーがログインを切り替えることを許可するとLoginView、再度表示される可能性がありApplicationViewます。 .

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    var login = new LoginDialog();
    var loginVm = new LoginViewModel();

    login.DataContext = loginVm;
    login.ShowDialog();

    if (!login.DialogResult.GetValueOrDefault())
    {
        Environment.Exit(0);
    }

    // Providing we have a successful login, startup application
    var app = new ApplicationView();
    var context = new ApplicationViewModel(loginVm.CurrentUser);
    app.DataContext = context;
    app.Show();
}

Application先ほど言ったように、を表示するときにを隠したくないDialogので、 のDialog部分をApplication

これは、ダイアログ用にブログから独自のカスタム ポップアップをDataTemplate使用して、 に使用する例です。ApplicationViewModel

<Grid x:Name="ApplicationView">
    <ContentControl Content="{Binding CurrentView}" />
    <local:PopupPanel x:Name="DialogPopup"
                      Content="{Binding DialogContent}"
                      local:PopupPanel.IsPopupVisible="{Binding IsDialogVisible}"
                      local:PopupPanel.PopupParent="{Binding ElementName=ApplicationView}" />
</Grid>
于 2012-06-21T13:27:16.110 に答える
0

個人的には、標準グリッド内で ZOrdering を使用し、すべてを同じビューに配置する方が簡単だと思います-ViewModel を使用して可視性を管理します。

例えば

<Grid>
    <Grid Visibility="{Binding IsView1Visible, 
        Converter={StaticResource BoolToVisibilityConverter}}">
        <!-- view 1 contents -->
    </Grid>
    <Grid Visibility="{Binding IsView2Visible, 
        Converter={StaticResource BoolToVisibilityConverter}}">
        <!-- view 2 contents -->
    </Grid>
    <Grid Visibility="{Binding IsView3Visible, 
        Converter={StaticResource BoolToVisibilityConverter}}">
        <!-- view 3 contents -->
    </Grid>
    <Grid Visibility="{Binding IsDialogVisible, 
        Converter={StaticResource BoolToVisibilityConverter}}">
        <!-- dialog contents contents -->
    </Grid>
</Grid>
于 2012-06-21T13:19:15.403 に答える