Visual Studio 2010でユーザー・インターフェイス開発:特集:Visual Studio 2010で社内C/Sシステム開発(前編)(3/3 ページ)
社内向けのクライアント/サーバ型システムを、最新の.NET環境で開発するには? サンプル・アプリの実装を通して解説。
■メニュー選択によるコンテンツ領域の切り替え
ここでは、メニューが選択されたときにコンテンツ領域を切り替える処理を実装する。
●コンテンツ領域となるユーザー・コントロールの作成
コンテンツ領域に表示するユーザー・コントロールを5つ作成しておこう。
[ソリューション エクスプローラー]にあるプロジェクト項目の右クリック・メニューから[追加]−[ユーザー コントロール]を実行する。[新しい項目の追加]ダイアログが表示されるので、下記の名前でファイルを作成する。
- ContetObentoOrder
- ContetObentoEntry
- ContetObentoList
- ContetUserEntry
- ContetUserList
WPFデザイナで、それぞれのユーザー・コントロールの.xamlファイルが表示されたら、TextBlockコントロールをドラッグ&ドロップで配置して、そのTextプロパティにファイルと同じ名前を設定しておこう。なおこれは、ユーザー・コントロールの切り替え状況が認識しやすいようにするための一時的な実装である。
●メニューのChecked/Uncheckedイベント・ハンドラ
メニューが選択された状態か/されていない状態かは、ToggleButtonコントロールのIsCheckedプロパティの値がTrueか/Falseかで判別できる。このIsCheckedプロパティが変更されたときに発行されるのが、Checked/Uncheckedイベント・ハンドラである。従ってここでは、5つのメニュー・ボタンのChecked/Uncheckedイベント・ハンドラを追加する。
これらのイベント・ハンドラも一括で設定しよう。一括してイベント・ハンドラを設定するには、[ドキュメント アウトライン]ウィンドウで[Ctrl]キーを押したまま、各ToggleButtonコントロールを次々とクリックして選択したうえで、[プロパティ]ウィンドウで[イベント]タブを開き、[Checked]イベントの入力欄に「Menu_Checked」を、[Unchecked]イベントの入力欄に「Menu_Unchecked」を指定すればよい。
Menu_Checked/Menu_Uncheckedメソッドが追加されるので、下記のコードに書き直してほしい。
using System.Windows;
using System.Windows.Controls.Primitives;
using Microsoft.Windows.Controls.Ribbon;
public MainWindow()
{
InitializeComponent();
ContentControlMain.Content = new ContetObentoOrder();
}
private void Menu_Checked(object sender, RoutedEventArgs e)
{
if (ContentControlMain != null)
{
SwitchContent(((ToggleButton)sender).Name);
}
}
private void SwitchContent(string senderName)
{
// 該当メニュー以外のチェックをオフにする。
// なお、クリックされたメニューは自動的にチェックが入る。
if (senderName != "MenuObentoOrder")
MenuObentoOrder.IsChecked = false;
if (senderName != "MenuObentoEntry")
MenuObentoEntry.IsChecked = false;
if (senderName != "MenuObentoList")
MenuObentoList.IsChecked = false;
if (senderName != "MenuUserEntry")
MenuUserEntry.IsChecked = false;
if (senderName != "MenuUserList")
MenuUserList.IsChecked = false;
switch (senderName)
{
case "MenuObentoOrder":
ContentControlMain.Content = new ContetObentoOrder();
ChangeRibbonTabVisibility(senderName);
break;
case "MenuObentoEntry":
ContentControlMain.Content = new ContetObentoEntry();
ChangeRibbonTabVisibility(senderName);
break;
case "MenuObentoList":
ContentControlMain.Content = new ContetObentoList();
ChangeRibbonTabVisibility(senderName);
break;
case "MenuUserEntry":
ContentControlMain.Content = new ContetUserEntry();
ChangeRibbonTabVisibility(senderName);
break;
case "MenuUserList":
ContentControlMain.Content = new ContetUserList();
ChangeRibbonTabVisibility(senderName);
break;
}
}
private void ChangeRibbonTabVisibility(string senderName)
{
if (senderName == "MenuObentoOrder")
TabObentoOrder.Visibility = Visibility.Visible;
if (senderName == "MenuObentoEntry")
TabObentoEntry.Visibility = Visibility.Visible;
if (senderName == "MenuObentoList")
TabObentoList.Visibility = Visibility.Visible;
if (senderName == "MenuUserEntry")
TabUserEntry.Visibility = Visibility.Visible;
if (senderName == "MenuUserList")
TabUserList.Visibility = Visibility.Visible;
if (senderName != "MenuObentoOrder")
TabObentoOrder.Visibility = Visibility.Hidden;
if (senderName != "MenuObentoEntry")
TabObentoEntry.Visibility = Visibility.Hidden;
if (senderName != "MenuObentoList")
TabObentoList.Visibility = Visibility.Hidden;
if (senderName != "MenuUserEntry")
TabUserEntry.Visibility = Visibility.Hidden;
if (senderName != "MenuUserList")
TabUserList.Visibility = Visibility.Hidden;
}
private void Menu_Unchecked(object sender, RoutedEventArgs e)
{
if (ContentControlMain != null)
{
if ((MenuObentoOrder.IsChecked == false) &&
(MenuObentoEntry.IsChecked == false) &&
(MenuObentoList.IsChecked == false) &&
(MenuUserEntry.IsChecked == false) &&
(MenuUserList.IsChecked == false))
{
((ToggleButton)sender).IsChecked = true;
}
}
}
Imports System.Windows.Controls.Primitives
Public Sub New()
InitializeComponent()
ContentControlMain.Content = New ContetObentoOrder()
End Sub
Private Sub Menu_Checked(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles MenuUserList.Checked, MenuUserEntry.Checked, MenuObentoList.Checked, MenuObentoEntry.Checked, MenuObentoOrder.Checked
If ContentControlMain IsNot Nothing Then
SwitchContent(DirectCast(sender, ToggleButton).Name)
End If
End Sub
Private Sub SwitchContent(ByVal senderName As String)
' 該当メニュー以外のチェックをオフにする。
' なお、クリックされたメニューは自動的にチェックが入る。
If senderName <> "MenuObentoOrder" Then
MenuObentoOrder.IsChecked = False
End If
If senderName <> "MenuObentoEntry" Then
MenuObentoEntry.IsChecked = False
End If
If senderName <> "MenuObentoList" Then
MenuObentoList.IsChecked = False
End If
If senderName <> "MenuUserEntry" Then
MenuUserEntry.IsChecked = False
End If
If senderName <> "MenuUserList" Then
MenuUserList.IsChecked = False
End If
Select Case senderName
Case "MenuObentoOrder"
ContentControlMain.Content = New ContetObentoOrder()
ChangeRibbonTabVisibility(senderName)
Exit Select
Case "MenuObentoEntry"
ContentControlMain.Content = New ContetObentoEntry()
ChangeRibbonTabVisibility(senderName)
Exit Select
Case "MenuObentoList"
ContentControlMain.Content = New ContetObentoList()
ChangeRibbonTabVisibility(senderName)
Exit Select
Case "MenuUserEntry"
ContentControlMain.Content = New ContetUserEntry()
ChangeRibbonTabVisibility(senderName)
Exit Select
Case "MenuUserList"
ContentControlMain.Content = New ContetUserList()
ChangeRibbonTabVisibility(senderName)
Exit Select
End Select
End Sub
Private Sub ChangeRibbonTabVisibility(ByVal senderName As String)
If senderName = "MenuObentoOrder" Then
TabObentoOrder.Visibility = Visibility.Visible
End If
If senderName = "MenuObentoEntry" Then
TabObentoEntry.Visibility = Visibility.Visible
End If
If senderName = "MenuObentoList" Then
TabObentoList.Visibility = Visibility.Visible
End If
If senderName = "MenuUserEntry" Then
TabUserEntry.Visibility = Visibility.Visible
End If
If senderName = "MenuUserList" Then
TabUserList.Visibility = Visibility.Visible
End If
If senderName <> "MenuObentoOrder" Then
TabObentoOrder.Visibility = Visibility.Hidden
End If
If senderName <> "MenuObentoEntry" Then
TabObentoEntry.Visibility = Visibility.Hidden
End If
If senderName <> "MenuObentoList" Then
TabObentoList.Visibility = Visibility.Hidden
End If
If senderName <> "MenuUserEntry" Then
TabUserEntry.Visibility = Visibility.Hidden
End If
If senderName <> "MenuUserList" Then
TabUserList.Visibility = Visibility.Hidden
End If
End Sub
Private Sub Menu_Unchecked(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles MenuUserList.Unchecked, MenuUserEntry.Unchecked, MenuObentoList.Unchecked, MenuObentoEntry.Unchecked, MenuObentoOrder.Unchecked
If ContentControlMain IsNot Nothing Then
If (MenuObentoOrder.IsChecked = False) AndAlso
(MenuObentoEntry.IsChecked = False) AndAlso
(MenuObentoList.IsChecked = False) AndAlso
(MenuUserEntry.IsChecked = False) AndAlso
(MenuUserList.IsChecked = False) Then
DirectCast(sender, ToggleButton).IsChecked = True
End If
End If
End Sub
コード内容の詳細は割愛するが、簡単に説明すると、クリックされたメニューを判定して、以前選択されていたメニューのチェック状態を解除し、さらにコンテンツ領域とリボン・タブの切り替えを行っている。
以上で、前編で目標とする基本部分は完成した。
■応用的なUI開発
今回のUIで気になるのは、選択されたメニューの外観が標準のボタンと変わらないところだ。そこでここでは、もう少しメニューらしい外観に変更してみよう。
●メニュー・ボタンの外観の変更
ここではToggleButtonコントロールの外観を変更する必要があるわけだが、このような場合、WPFでは「コントロール・テンプレート」という機能を用いる。
具体的には、WPFデザイナなどで対象のToggleButtonコントロールを選択したうえで、[プロパティ]ウィンドウの[Template]プロパティの右クリック・メニューから[値をリソースに抽出]を実行する。これにより、[リソースの作成]ダイアログが表示されるので、[キー]欄に任意の名前(今回は「TemplateMenu」)と入力して[OK]ボタンをクリックする。
これにより、XAMLコードの<r:RibbonWindow.Resources>要素内に<ControlTemplate>要素が追加されるので、これを例えば下記のように書き換えればよい。
<LinearGradientBrush x:Key="BackgroundMenuMouseOver"
EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFF7F7F7" Offset="0" />
<GradientStop Color="#FFABABAB" Offset="1" />
</LinearGradientBrush>
<ControlTemplate x:Key="TemplateMenu" TargetType="ButtonBase">
<my:ButtonChrome Background="{TemplateBinding Control.Background}" BorderBrush="{TemplateBinding Control.BorderBrush}" Name="Chrome" RenderDefaulted="{TemplateBinding Button.IsDefaulted}" RenderMouseOver="{TemplateBinding UIElement.IsMouseOver}" RenderPressed="{TemplateBinding ButtonBase.IsPressed}" SnapsToDevicePixels="True">
<ContentPresenter Content="{TemplateBinding ContentControl.Content}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" Margin="{TemplateBinding Control.Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" />
</my:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsKeyboardFocused" Value="True">
<Setter Property="my:ButtonChrome.RenderDefaulted" TargetName="Chrome" Value="True" />
</Trigger>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter Property="Control.Foreground" Value="#FFADADAD" />
</Trigger>
<!--IsMouseOverを追加。IsCheckedを修正。-->
<Trigger Property="UIElement.IsMouseOver" Value="true">
<Setter Property="my:ButtonChrome.RenderMouseOver" TargetName="Chrome" Value="false" />
<Setter Property="Control.Background" TargetName="Chrome" Value="{StaticResource BackgroundMenuMouseOver}" />
<Setter Property="Control.Foreground" Value="Orange" />
<Setter Property="Control.FontWeight" Value="Bold" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter Property="my:ButtonChrome.RenderPressed" TargetName="Chrome" Value="false" />
<Setter Property="Control.Background" TargetName="Chrome" Value="Indigo" />
<Setter Property="Control.Foreground" Value="White" />
<Setter Property="Control.FontWeight" Value="Bold" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
コード中のmy名前空間は、コントロール・テンプレートのコードが自動生成された際に自動追加されたもの。具体的には、<r:RibbonWindow>要素に「xmlns:my="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"」のような記述で定義されている。
こちらもコード内容の詳細は割愛するが、簡単に説明すると、<Trigger Property="UIElement.IsMouseOver" Value="true">要素や<Trigger Property="ToggleButton.IsChecked" Value="True">要素内で各種プロパティを設定している。ポイントは、下記のコードによるプロパティ設定で「false」を設定しているところだ。こうしないと、デフォルトのレンダリング処理により、背景色などのプロパティが正常に動作しない。
<Setter Property="my:ButtonChrome.RenderMouseOver" TargetName="Chrome" Value="false" />
<Setter Property="my:ButtonChrome.RenderPressed" TargetName="Chrome" Value="false" />
以上でコントロール・テンプレートの作成は完了したので、ほかのToggleButtonコントロールにも適用する。一括で適用するには、[ドキュメント アウトライン]ウィンドウで[Ctrl]キーを押したまま、各ToggleButtonコントロールを次々とクリックして選択したうえで、[プロパティ]ウィンドウの[Template]プロパティの右クリック・メニューから[リソースの適用]を実行する。次の画面のように表示されるので、先ほど作成したコントロール・テンプレートを選択すればよい。
ここでビルドして実行したのが次の画面だ。
ここまでに作成したサンプル・プログラムのソース・コードは下記のリンクからダウンロードできる。
今回はここまでとする。次回は、データベース関係の処理を実装する。
Copyright© Digital Advantage Corp. All Rights Reserved.