Region Navigation

View-Switching Navigationの続きですが、2つめのWPFにしては複雑すぎるものに手を出してしまった感じ。
コードを読んでPrism6に書き換えるのは今の私の知識ではどう考えても無理。
デザインもxamlの知識が無いので躓いた箇所は後回し。
Prism6公式のサンプルを参照しながら元ネタに近いものを仕上げる方針に変えました。
左側メインメニューにモジュールを切り替えるボタンを追加するのに、Region Navigationを使ってみました。

メニュー用View追加

左側のRegion(MainNavigationRegion)に表示するメニューボタン用Viewを追加します。
テンプレート:Prism UserControl
ファイル名:CalendarNavigationItemView.xaml
viewswich130.png

Viewのテスト用のTextBlockを追加。
CalendarModule.csの修正
public void Initialize()
{
    //_regionManager.RegisterViewWithRegion("MainContentRegion", typeof(Views.CalendarView));
    _regionManager.RegisterViewWithRegion(RegionNames.MainNavigationRegion, typeof(CalendarNavigationItemView));
}
この時点では未だView-Switching Navigationのソースに近い形でいくつもりだったので、CalendarViewをコメントアウトし、CalendarNavigationItemViewを追加。
実行してMainNavigationRegionに表示されていることを確認。
viewswich140.png

ナビゲーション用ボタン作成

サンプルからCalendarNavigationItemView.xamlのソースをそのままコピー。
viewswich150.png

MainWindow.xamlの時と同じくエラーが出るので、ネームスペースとプロジェクトの参照を追加。
viewswich160.png

エラーの出るButton_Clickと不要なStyle属性削除して実行して確認。
Material Designを適用し忘れたら下記のような感じ。
ボタンを揃えるにはモジュール追加する毎にまったく同じことを繰り返すか、ユーザーコントロールを作るか、モジュール用のテンプレートを充実させていくかする必要がありそう。
viewswich210.png

ナビゲーション機能の追加

エラーを潰しながら組み込み始めたのですが、System.ComponentModel.Compositionが見つからずNugetで追加する必要があることが分かり方向転換。
(テンプレートに含まれていないということは今の主流から外れそうなので)
Prism6のサンプルプロジェクトの中で一番近そうな17-BasicRegionNavigationを真似することにしました。
<UserControl x:Class="ViewSwitchingNavigation.Calendar.Views.CalendarNavigationItemView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True"
             xmlns:controls="clr-namespace:ViewSwitchingNavigation.Controls;assembly=ViewSwitchingNavigation.Controls"
             >
    <Grid x:Name="LayoutRoot">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Button Command="{Binding NavigateCommand}" CommandParameter="CalendarView" Margin="5">calendar</Button>
        <!--<RadioButton x:Name="NavigateToCalendarRadioButton" GroupName="MainNavigation" IsChecked="{Binding NavigateCommand}" CommandParameter="CalendarView" AutomationProperties.AutomationId="CalendarRadioButton">Calendar</RadioButton>-->
        <controls:InfoTipToggleButton Grid.Column="1">
            <controls:InfoTipToggleButton.Popup>
                <Popup>
                    <Border BorderBrush="Black" BorderThickness="2">
                        <StackPanel MinWidth="100" MinHeight="24" MaxWidth="400" Background="White">
                            <TextBlock TextWrapping="Wrap">This button demonstrates navigation to a view that that supports cross-navigation to another area.</TextBlock>
                        </StackPanel>
                    </Border>
                </Popup>
            </controls:InfoTipToggleButton.Popup>
        </controls:InfoTipToggleButton>
    </Grid>
</UserControl>
RadioButtonに Command="Binding NavigateCommand" を追加する方法が分からなかったので、Prism6のサンプルにあわせボタンに変更。現在アクティブなボタンの色を変えるのは一通り動いた後余裕があれば。
ボタンのxamlをモジュール側で記述するように変えたので、NavigateCommandをどこに記述するか悩み最初はViewSwitchingNavigation.CalendarにViewModelを追加して動作確認できましたが、同じことを他のモジュールでも行うのが面倒なのと、上記のxamlがNavigateCommand追加前でもエラーにならなかったので親プロジェクトの既存のViewModelに移動したところ、問題なく動きました。
viewswich220.png

カタログにモジュール追加する順序を変えてみた

viewswich230.png

保証されているかどうか確認はしていませんが、上下を変えたら変わり、戻したら戻りました。

View-Switching Navigation

Prism5.0のQuickstarts View-Switching NavigationをVS2017でMaterial Design In XAML Toolkitを使って最後までたどり着けるかな?

ソリューション&親プロジェクト作成

  • テンプレート:Prism Unity App(WPF)(QuickstartsではMEFが使われてました…。ここからUnity版を選んでダウンロードしたはずなのですが。とりあえずこのままUnityで続けます)
  • プロジェクト名:ViewSwitchingNavigation
※Prismのテンプレートが見つからない場合は、Hello World(2017版)を参照してテンプレートをインストールしてください。
viewswich010.png

共有コード用プロジェクト追加

  • テンプレート:通常のクラスライブラリ
  • プロジェクト名:ViewSwitchingNavigation.Infrastructure
viewswich020.png

ユーザーコントロール用プロジェクト追加

  • テンプレート:WPFユーザーコントロールライブラリ(.NET Framework)…なんと「Windowsクラシック デスクトップ」の下に。始めたばかりだと言うのにクラシック扱いされてます。
  • プロジェクト名:ViewSwitchingNavigation.Controls
viewswich025.png

モジュール側プロジェクト追加

  • テンプレート:Prism Module(WPF)
  • プロジェクト名:ViewSwitchingNavigation.Calendar,ViewSwitchingNavigation.Contacts,ViewSwitchingNavigation.Emailの3つ(実際に仕事で使う場合は一つだけ作ってテンプレート化した方が楽でしょう。練習兼ねて3回同じこと繰り返します(まだそのつもり段階ですが)
viewswich030.png

NuGetでパッケージ追加

パッケージ管理画面起動

viewswich035.png

MaterialDesignThemesを追加

XAMLのViewを追加しそうなプロジェクトにはチェックを入れる。
viewswich036.png

Prism関連を追加

不要かもしれませんが、ついでに。
viewswich037.png

モジュール側View追加

ViewSwitchingNavigation.CalendarプロジェクトのViewsフォルダにCalendarView.xamlを追加
Prism UserControlのテンプレートを使うとxamlにPrism関連のネームスペースが追加されています。
viewswich040.png

親プロジェクトから他のプロジェクトへ参照追加

ViewSwitchingNavigationプロジェクトの「参照」を右クリックして「参照の追加」を選択。
viewswich060.png

プロジェクトの下のソリューションを選択して一応全てにチェックを入れる(自信なし)。
viewswich050.png

Hello Woldのおさらい

Hello World(2017版)のViewSwitchingNavigation.Calendar版。
これまで順調に進んでいることを確認。
viewswich070.png

親プロジェクトのMainWindow.xamlを修正

タイトル追加、MainNavigationRegionを追加。
ユーザーコントロール(カスタムコントロール?まだ違いが分かりません)が使われていてエラーになる部分はカット。
viewswich080.png

ユーザーコントロールの追加

ViewSwitchingNavigation.ControlsプロジェクトにユーザーコントロールInfoTipToggleButton.xamlを追加。
追加→既存項目でダウンロードしたものそのまま移植するかコードをコピペ。
新規追加してコードを追加する場合は赤枠あたりに注意。InfoTipToggleButton.xaml.csファイルの修正も忘れずに。
viewswich090.png

親プロジェクトのMainWindow.xamlの上でカットした部分を追加
viewswich100.png

実行してInfoTipToggleButtonの動作確認。
viewswich110.png

Material Designを組み込む

InfoTipToggleButtonが動かない…。画像をButtonに変えたらボタンのクリックイベントが先に走る…。状態が取れない…。標準のボタンでいいような気がして今は無視。
viewswich120.png

親プロジェクトのApp.xaml(一部)色の指定はこちらで。
<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
            <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
            <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
            <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>
親プロジェクトのMainWindow.xaml(ボタン動かないバージョン)
<Window x:Class="ViewSwitchingNavigation.Views.MainWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
        xmlns:controls="clr-namespace:ViewSwitchingNavigation.Controls;assembly=ViewSwitchingNavigation.Controls"
        TextElement.Foreground="{DynamicResource MaterialDesignBody}"
        Background="{DynamicResource MaterialDesignPaper}"
        TextElement.FontWeight="Medium"
        TextElement.FontSize="14"
        FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
        Title="{Binding Title}"
        d:DesignHeight="300" d:DesignWidth="400">

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Button.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Shadows.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.ToggleButton.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <DockPanel>
        <materialDesign:ColorZone Padding="16" materialDesign:ShadowAssist.ShadowDepth="Depth2"
                                    Mode="PrimaryMid" DockPanel.Dock="Top">
            <DockPanel>
                <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="22">View-Switching Navigation</TextBlock>
                <controls:InfoTipToggleButton DockPanel.Dock="Right">
                    <controls:InfoTipToggleButton.Popup>
                        <Popup>
                            <StackPanel MinWidth="100" MinHeight="24" MaxWidth="500" Background="White">
                                <TextBlock TextWrapping="Wrap" Style="{StaticResource MaterialDesignBody2TextBlock}" Padding="6">This Navigation Quickstart demonstrates navigation within Prism's Regions to show new views, move between existing views, and how to pass context to views during navigaton.</TextBlock>
                            </StackPanel>
                        </Popup>
                    </controls:InfoTipToggleButton.Popup>
                </controls:InfoTipToggleButton>
            </DockPanel>
        </materialDesign:ColorZone>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>

            <Border Grid.Column="0" Grid.Row="2" MinWidth="250" Margin="5,0,0,5">
                <ItemsControl x:Name="NavigationItemsControl" prism:RegionManager.RegionName="MainNavigationRegion" Grid.Column="0" Margin="5" Padding="5" />
            </Border>
            <ContentControl prism:RegionManager.RegionName="MainContentRegion" 
                Grid.Column="1" Grid.Row="2" Margin="5,0,5,5" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>

        </Grid>
    </DockPanel>
</Window>

Material Design In XAML Toolkit

2017/06/20 WPF::Material Design
チュートリアルやるにしてもデザインが綺麗だとテンション上がりますよね。
Webアプリではbootstrapのお世話になってますが、WPFで使えるデザインフレームワークはないのかしらと調べたら、metroではなくMaterial Design版が見つかりました。(metroも見つかりました
Xamarinのお陰かも知れませんが、ありがたく使わせていただくことにしました。
プロジェクトはここの続きです。

Prism7を使ってやり直し中です(2018/12/22追記)

インストール

nugetでMaterialDesignThemesで検索
material010.png

とりあえず両方にチェック。

HelloWorld.Desktop側の修正

App.xamlの下記の間に
<Application.Resources>
</Application.Resources>
下記を追加
<ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
        <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />                
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

HelloWorldModule側の修正

HelloWorldView.xamlを修正
<UserControl x:Class="HelloWorldModule.Views.HelloWorldView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:local="clr-namespace:HelloWorldModule.Views"
        mc:Ignorable="d" 
        d:DesignHeight="300"
        d:DesignWidth="300"
        xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
        TextElement.Foreground="{DynamicResource MaterialDesignBody}"
        TextElement.FontWeight="Regular"
        TextElement.FontSize="13"
        TextOptions.TextFormattingMode="Ideal" 
        TextOptions.TextRenderingMode="Auto"        
        Background="{DynamicResource MaterialDesignPaper}"
        FontFamily="{DynamicResource MaterialDesignFont}">
    <Grid>
        <materialDesign:Card Padding="32" Margin="16">
            <TextBlock Style="{DynamicResource MaterialDesignTitleTextBlock}">Hello World</TextBlock>
        </materialDesign:Card>
    </Grid>
</UserControl>
material020.png

青線が波打ってますが…
material030.png

実行してみたらちゃんと表示されました。
これは楽しくなりそう。

続きはこちらで
OK キャンセル 確認 その他