MVVMでさまざまなページを表示するメニューを作成する最良の方法は何ですか?
-
06-07-2019 - |
質問
MVVMパターンを使用して簡単なアプリケーションを構築したい。
このアプリケーションには2つの主要部分があります:
-
上部の
- メニュー
- コンテンツ以下
ナビゲーションは簡単です:
- 各メニュー項目(例:「顧客の管理」や「レポートの表示」)は、特定の機能を備えた新しいページでコンテンツ領域を埋めます li>
メニュー項目のコードビハインドイベントハンドラーにすべてのページが読み込まれ、表示されるべきページがStackPanelの子として読み込まれた場合、コードビハインドでこれを行った。ただし、手動でStackPanelに入力したくはないが表示されるため、MVVMでは機能しません。 " PageItem" DataTemplateなどのオブジェクト
では、MVVMを使用してこのような単純なクリックメニューアプリケーションを作成した人は、基本的なアプリケーション構造はどうでしたか?これらの線に沿って考えています:
MainView.xaml:
<DockPanel LastChildFill="False">
<Menu
ItemsSource="{Binding PageItemsMainMenu}"
ItemTemplate="{StaticResource MainMenuStyle}"/>
<ContentControl
Content="{Binding SelectedPageItem}"/>
</DockPanel>
メニューには&quot; PageItems&quot;のコレクションが表示されます。 DataTemplateには、各&quot; PageItemオブジェクト&quot;のタイトルが表示されます。各MenuItemのヘッダーとして。
そして、ContentControlは、完全な機能を備えたView / ViewModelペアで満たされますが、これについてはわかりません。
解決
まず、コードビハインドイベントハンドラーを保持する必要があると思います。実用的な理由もなく、単純な2行のイベントハンドラーを複雑なコマンド駆動型モンスターに変更しても意味がありません(そして、これがメインですメニュー、アプリを実行するたびにテストされます)。
今、あなたが純粋なMVVMルートに行きたいなら、あなたのメニューにコマンドを発させるためにあなたがしなければならないすべては、最初に、いくつかのリソースセクションでこのスタイルを追加します:
<Style x:Key="MenuItemStyle" TargetType="MenuItem">
<Setter Property="Command"
Value="{Binding DataContext.SwitchViewCommand,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Menu}}}"/>
<Setter Property="CommandParameter"
Value="{Binding}"/>
</Style>
このスタイルは、MenuItemのDataContextをコマンドパラメーターとして、接続されたビューモデルでSwitchViewCommandをメニュー項目に起動させます。
実際のビューは、ItemContainerStyleとしてそのスタイルへの追加の参照を含むコードと同じです(したがって、DataTemplateのコンテンツではなく、メニュー項目に適用されます):
<DockPanel LastChildFill="False">
<Menu DockPanel.Dock="Top"
ItemsSource="{Binding PageItemsMainMenu}"
ItemTemplate="{StaticResource MainMenuStyle}"
ItemContainerStyle="{StaticResource MenuItemStyle}"/>
<ContentControl
Content="{Binding SelectedPageItem}"/>
</DockPanel>
必要なビューモデルで(PageItemコードがないため文字列を使用しました):
private string _selectedViewItem;
public List<string> PageItemsMainMenu { get; set; }
public string SelectedPageItem
{
get { return _selectedViewItem; }
set { _selectedViewItem = value; OnNotifyPropertyChanged("SelectedPageItem"); }
}
public ICommand SwitchViewCommand { get; set; }
そして、コマンドがこのコードを呼び出すようにするために使用するコマンドクラスを使用します。
private void DoSwitchViewCommand(object parameter)
{
SelectedPageItem = (string)parameter;
}
現在、ユーザーがメニュー項目をクリックすると、メニュー項目はページ項目をパラメーターとしてSwitchViewCommandを呼び出します。
コマンドは、SelectedPageItemプロパティを設定するDoSwitchViewCommandを呼び出します
このプロパティは、データバインディングを介してUIを更新するNotifyPropertyChangedを発生させます。
または、2行のイベントハンドラを自由に作成できます
他のヒント
iは、すべてのページをメニューから呼び出し可能にするVMのObservableCollectionを想像できます。 次に、ItemsControlとContentControlをバインドして、ContentControlが常にそのリストのCurrentItemを表示するようにします。 もちろん、メニューは一部のTitleプロパティにのみバインドします 一方、ContentControlはアイテム全体を採用し、タイプに応じて適切なビューをプラグインします。
別のオプションは、メニューの代わりにリストボックスを使用し、リストボックスのスタイルをメニューのように設定し、次のように選択した値にバインドすることです:
<DockPanel LastChildFill="False">
<ListBox
ItemsSource="{Binding PageItemsMainMenu}"
ItemTemplate="{StaticResource MainMenuStyle}"
IsSynchronizedWithCurrentItem="True"/>
<ContentControl
Content="{Binding PageItemsMainMenu/}"/>
</DockPanel>
IsSynchronizedWithCurrentItem =&quot; True&quot;に注意してください。選択されたアイテムと{Binding PageItemsMainMenu /}を末尾のスラッシュで設定して使用します。