私は複数のビューを持つWPFアプリケーションを持っています。ビュー1からビュー2に切り替え、そこから複数のビューに切り替えられるようにしたいのです。そこで、ビュー1のボタンを押すと、同じウィンドウにビュー2がロードされるようにしたいのです。
それらのことを試してみましたが、うまくいきません‼。
最初のリンクから、問題は私がViewModelLocatorのコードを理解していないこと'である。彼らは CreateMain();
関数を呼び出しますが、これはどこに定義されているのでしょうか。また、ビューの内部から別のビューに切り替えるにはどうすればよいのでしょうか。
まず、MVVMを実装するために、これらのツールキットやフレームワークは必要ありません。例えば、 MainViewModel
と PersonViewModel
と CompanyViewModel
があり、それぞれが関連するビューを持っていて、それぞれが abstract
ベースクラス BaseViewModel
を拡張していると仮定します。
BaseViewModelでは、共通のプロパティと
ICommandインスタンスを追加して、
INotifyPropertyChangedインターフェースを実装することができます。これらは全て
BaseViewModelクラスを継承しているので、
MainViewModel` クラスにこのプロパティを持たせて、どのビューモデルにも設定できるようにすることができます。
public BaseViewModel ViewModel { get; set; }
もちろん、この簡単な例とは異なり、INotifyPropertyChanged
インターフェイスを あなたの プロパティに正しく実装する必要があります。さて、App.xaml
では、ビューとビューモデルを接続するために、いくつかの簡単な DataTemplate
を宣言しています。
<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
インスタンスを使用する場合、これらの DataTemplate
はフレームワークに関連するビューを代わりに表示するように伝えます。このように表示することができます。
<ContentControl Content="{Binding ViewModel}" />
つまり、新しいビューに切り替えるために必要なことは、MainViewModel
クラスから ViewModel
プロパティを設定することだけです。
ViewModel = new PersonViewModel();
最後に、他のビューからビューを変更するにはどうすればよいのでしょうか。いくつかの方法が考えられますが、最も簡単な方法は、子ビューの Binding
を MainViewModel
の ICommand
に直接追加することです。私は 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}" />
以上です。お楽しみに。
たぶんこれのリンクが役に立つと思います。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"
をバインドすることができます。Windowの
ContentControlをターゲットにするには、
RelativeSource` バインディングを使用します。例えば、以下のようになります。
meffed:NavigationExtensions.NavigationHost="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}},Path=ViewContainer}"
になります。
それぞれのビューで、クラス定義の後ろのコードに [NavigationView("firstview")]
などと注釈を付けることを確認してください。
初めてだとややこしいですが、一度理解すればとても簡単です。