web-dev-qa-db-ja.com

WPF MVVMナビゲートビュー

複数のビューを持つWPFアプリケーションがあります。ビュー1からビュー2に切り替え、そこから複数のビューに切り替えることができます。そのため、同じウィンドウでview2をロードするビュー1のボタンが必要です。

私はそれらのことを試してみましたが、動作させることができません。

最初のリンクからの問題は、ViewModelLocatorコードが理解できないことです。それらはCreateMain();関数を呼び出しますが、これはどこで定義されていますか。また、ビュー内から別のビューに切り替える方法を教えてください。

41
user2499088

まず、MVVMを実装するためにこれらのツールキット/フレームワークは必要ありません。これと同じくらい簡単です... MainViewModelPersonViewModelCompanyViewModelがあり、それぞれに関連するビューがあり、それぞれがabstract基本クラスBaseViewModelを拡張していると仮定しましょう。

BaseViewModelでは、共通のプロパティやICommandインスタンスを追加し、INotifyPropertyChangedインターフェイスを実装できます。これらはすべてBaseViewModelクラスを拡張するため、ビューモデルのいずれかに設定できるMainViewModelクラスにこのプロパティを含めることができます。

public BaseViewModel ViewModel { get; set; }

もちろん、この簡単な例とは異なり、yourプロパティにINotifyPropertyChangedインターフェイスを正しく実装することになります。今 App.xaml、簡単なDataTemplatesを宣言して、ビューをビューモデルに接続します。

<DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
    <Views:MainView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:PersonViewModel}">
    <Views:PersonView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:CompanyViewModel}">
    <Views:CompanyView />
</DataTemplate>

これで、アプリケーションでBaseViewModelインスタンスの1つを使用する場合はいつでも、これらのDataTemplatesは、代わりに関連するビューを表示するようフレームワークに指示します。次のように表示できます。

<ContentControl Content="{Binding ViewModel}" />

したがって、新しいビューに切り替えるために必要なことは、ViewModelクラスからMainViewModelプロパティを設定することだけです。

ViewModel = new PersonViewModel();

最後に、ビューを他のビューからどのように変更しますか?これにはいくつかの方法がありますが、最も簡単な方法は、子ビューからBindingICommandMainViewModelに直接追加することです。私はRelayComandのカスタムバージョンを使用しますが、好きなタイプを使用でき、画像が得られると思います。

public ICommand DisplayPersonView
{
    get { return new ActionCommand(action => ViewModel = new PersonViewModel(), 
        canExecute => !IsViewModelOfType<Person>()); }
}

子ビューXAMLで:

<Button Command="{Binding DataContext.DisplayPersonView, RelativeSource=
    {RelativeSource AncestorType={x:Type MainView}}, Mode=OneWay}" />

それでおしまい!楽しい。

109
Sheridan

MVVMで初めて起動したとき、異なるMVVMフレームワーク、特にナビゲーション部分にも苦労しました。したがって、私は、レイチェルリムが作成したこの小さなチュートリアルを使用します。とてもいい説明です。

次のリンクをご覧ください。

それがあなたを助けたことを願っています:)

7
mskydt86

多分 this リンクが役立ちます。 NavigateToプロパティを、ウィンドウに表示する必要があるビューに設定するだけです。

例として、次のようなことができます

_<Window x:Class="MainWindowView" xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
                                 xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
                                 xmlns:d="http://schemas.Microsoft.com/expression/blend/2008"
                                 xmlns:meffed="http:\\www.codeplex.com\MEFedMVVM"
                                 meffed:ViewModelLocator.NonSharedViewModel="YourViewModel"
                                 WindowStartupLocation="CenterScreen">

    <Button meffed:NavigationExtensions.NavigateTo="firstview"
                    meffed:NavigationExtensions.NavigationHost="{Binding ElementName=_viewContainer}"
                    meffed:NavigationExtensions.NavigateOnceLoaded="False"
                    Visibility="Visible" />

    <ContentControl x:Name="_viewContainer" Margin="0,0,0,10" />
<Window>
_

クラスファイルは次のようになります

_public partial class MainWindowView : Window
{
    public MainWindowView()
    {           
              InitializeComponent();
    }

        public ContentControl ViewContainer { get { return _viewContainer; } }

    }
_

次に、各ビューをUserControlとして定義し、上記のリンクを使用して、ボタンの_meffed:NavigationExtensions.NavigateTo="secondView"_をバインドします。 ContentControlWindowをターゲットにするには、RelativeSourceバインディングを使用します。例えば

_meffed:NavigationExtensions.NavigationHost="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}},Path=ViewContainer}"_

各ビューで、クラス定義の背後にあるコードに[NavigationView("firstview")]などの注釈を付けていることがわかります。

初めて複雑になりますが、アイデアを理解すれば非常に簡単になります。

1
Sandesh
<ContentControl x:Name="K.I.S.S" Content="{Binding ViewModel, Converter={StaticResource ViewLocator}}"/>
1
atomaras