サンプル2:会議室予約
続いて作成するのは、会議室を予約するWebアプリケーションをSilverlightで構築するサンプルです。コントロールで各種データを入力するイメージをつかみましょう。サンプルではコントロールから入力内容を取得し、ダイアログに表示するところまでを扱います。
使用するコントロールについて概説
サンプル2で使用する各コントロールについて概説します。
CalenderおよびDatePicker
カレンダーを表示するコントロールです。Calenderコントロール単体で使用し、カレンダーだけを表示することもできます。DatePickerコントロールを利用すれば、日付選択時のドロップダウンメニューとしてカレンダーが利用できます。
| 名前 | 概要 | 
| DisplayDateStart | 表示する日付の開始日を指定 | 
| DisplayDateEnd | 表示する日付の終了日を指定 | 
| IsTodayHighlighted | 当日をハイライトするかどうかを指定 | 
| BlackoutDates | ブラックアウトさせて選択できないようにする日付を指定 | 
| DisplayMode | 一度に表示する期間を設定 | 
| SelectedDateFormat | DatePickerで選択する日付のフォーマットを指定 | 
RadioBotton
 ラジオボタンを表示するコントロールです。GroupNameプロパティを利用して複数のラジオボタンをグループ化できます。グループ化されたラジオボタンは排他的になり、複数のボタンを同時に選択できなくなります。ボタンの選択状態はIsCheckedプロパティで取得できます。
| 名前 | 概要 | 
| GroupName | ラジオボタンをグループ化するための文字列を設定 | 
| IsChecked | 選択状態の取得・設定 | 
| Content | 選択肢のテキストを設定 | 
| Checked | チェック時のイベントハンドラを設定 | 
| UnChecked | チェック解除時のイベントハンドラを設定 | 
ComboBoxおよびComboBoxItem
コンボボックスを表示するコントロールです。ComboBox以下にComboBoxItemを利用し静的なオプションを配置することができます。またデータバインドにより動的なオプションを取り込むこともできます。データバインドについては次回の連載で扱います。
| 名前 | 概要 | 
| SelectionChanged | 選択変更時のイベントハンドラを設定 | 
| IsSelected | 選択状態の取得・設定 | 
| ItemsSource | データバインドするアイテムのソースを指定 | 
CheckBox
チェックボックスを表示するコントロールです。基本的には選択および解除の2状態ですが、プロパティ設定で選択、解除に加えて中間ステートも含めた3状態(スリーステート)で利用することもできます。
| 名前 | 概要 | 
| Content | 選択肢のテキストを設定 | 
| IsThreeState | 中間ステートをサポートするかどうかの設定 | 
| Checked | チェック時のイベントハンドラを設定 | 
| Indeterminate | 中間状態設定時のイベントハンドラを設定 | 
| UnChecked | チェック解除時のイベントハンドラを設定 | 
サンプルの実装
サンプル2はサンプル1に追記する形で構成します。Main.xamlはサンプル1では遷移完了のテキストを表示するのみの役割でしたが、サンプル2で会議室予約画面として再構成しましょう。Main.xamlをExpression Blend 2で開き編集します。
まず、もともとのテキストオブジェクトを消去しましょう。[オブジェクトとタイムライン]でTextBlockを選択の上、右クリックから削除できます。
続いてルーラー上で区切り線をドラッグしてGridレイアウトを変更します。タイトル配置用に上段Gridを狭めに定義し、下段には入力コントロール用の適度な領域を確保します。
データの入力にはDatePicker、RadioButton、ComboBox、CheckBox、Buttonの各コントロールを配置しました。サンプル1と同様の方法でドロップしスタイルを整えます。TextBoxも3つ配置します。ComboBox内のアイテムは、[オブジェクトとタイムライン]での右クリックから[ComboBoxItemの追加]で挿入します。
今回、ComboBoxはデフォルトでは表示させず、チェックボックスをチェックした場合にイベントハンドラで表示させるようにします。他の入力コントロールにはイベントハンドラを設定せず、Buttonクリック時にまとめてデータ取得および出力を実行します。
RadioButtonのレイアウトではオプションの配置にStackPanelコントロールを使いました。StackPanelに配置したいオブジェクトを複数選択し、右クリックから[グループ化]-[StackPanel]を選択して利用します。
各コントロールに設定した主なプロパティおよびイベントハンドラについて、以下の表に示します。
| コントロール | 名前 | 値 | 
| DatePicker | 名前(x:Name) | dtp | 
| IsTodayHighlighted | true(チェックを入れる) | |
| RadioButton | 名前(x:Name) | am,pm,all | 
| Content | (コントロールに表示するテキスト) | |
| GroupName | radio | |
| ischecked | true(デフォルト選択のamのみチェックを入れる) | |
| ComboBox | 名前(x:Name) | combo | 
| Visibility | Collapsed(非表示) | |
| ComboBoxItem | 名前(x:Name) | m_1,m_2,m_3 | 
| Content | (コントロールに表示するテキスト) | |
| IsSelected | true(デフォルト選択のm_1のみチェックを入れる) | |
| CheckBox | 名前(x:Name) | pr | 
| Content | 部屋を選択する | |
| Checked(イベント) | cb_Checked | |
| UnChecked(イベント) | cb_UnChecked | |
| Button | Content | 決定 | 
| Click(イベント) | Button_Click | |
| TextBlock | Text | (コントロールに表示するテキスト) | 
実際のXAMLは次のとおりです。
<TextBlock Height="26" Grid.Row="0" Grid.Column="0" Margin="30,17,0,0" VerticalAlignment="Top" TextWrapping="Wrap" Foreground="#FF000000" Width="109" HorizontalAlignment="Left"><Run FontSize="14" Text="会議室予約画面"/></TextBlock>
<TextBlock Height="18" Margin="53,28,125,0" VerticalAlignment="Top" Text="希望する日付および時間帯を選択してください。" TextWrapping="Wrap" RenderTransformOrigin="0.392,0.667" Grid.Row="1"/>
<basics:DatePicker x:Name="dtp" Width="150" Height="30" Margin="96,57,154,0" d:LayoutOverrides="Width, Height" VerticalAlignment="Top" Grid.Row="1" IsEnabled="True" IsTodayHighlighted="True" IsDropDownOpen="False"/>
<StackPanel Height="67" Margin="96,95,172,0" VerticalAlignment="Top" Grid.Row="1">
    <RadioButton x:Name="am" GroupName="radio1" Content="午前(09:00-12:00)"  IsChecked="true" Height="17" Width="132" IsEnabled="True"/>
    <RadioButton x:Name="pm" GroupName="radio1" Content="午後(13:00-17:00)"  d:LayoutOverrides="Height" Width="132"/>
    <RadioButton x:Name="all" GroupName="radio1" Content="全日(09:00-17:00)"  Height="17" Width="132"/>
</StackPanel>
<TextBlock HorizontalAlignment="Left" Margin="61,185,0,0" VerticalAlignment="Top" Grid.Row="1" TextWrapping="Wrap" d:LayoutOverrides="Width, Height" Text="会議室の指定(指定しない場合は第一会議室が選択されます)"/>
<ComboBox x:Name="combo"  Height="21" Margin="0,217,58,0" VerticalAlignment="Top" Grid.Row="1" RenderTransformOrigin="1.62,0.476" Width="108" HorizontalAlignment="Right" Visibility="Collapsed">
    <ComboBoxItem x:Name="m_1" Content="第一会議室" IsSelected="True"/>
    <ComboBoxItem x:Name="m_2" Content="第二会議室"/>
    <ComboBoxItem x:Name="m_3" Content="第三会議室"/>
</ComboBox>
<CheckBox x:Name="pr" Content="部屋を選択する" Checked="cb_Checked" Unchecked="cb_Unchecked" Height="17" Margin="96,217,0,0" VerticalAlignment="Top" Grid.Row="1" Width="97" HorizontalAlignment="Left"/>
<Button Height="23" Margin="0,0,58,243" VerticalAlignment="Bottom" Grid.Row="1" Content="決定" Width="62" HorizontalAlignment="Right" Click="Button_Click"/>
</Grid>
続いて分離コードファイルMain.xaml.csを編集し、チェックボックスのチェック時、チェック解除時、ボタンクリック時のイベントを記述します。
 cb_Checked/cb_Uncheckedメソッドでは、ComboBoxの表示/非表示を切り替えています。また、不可視時にはComboBoxの選択の初期化も行っています。これらはビハインドコードからXAMLのコントロールを操作する一例です。また、ButtonのClickイベントによりデータの取得および出力を行います。
private void cb_Checked(object sender, RoutedEventArgs e)
{ //チェックボックスがチェックされた場合はコンボボックスを可視化
  combo.Visibility = Visibility.Visible;
}
private void cb_Unchecked(object sender, RoutedEventArgs e)
{ //チェックボックスがチェック解除された場合はコンボボックスを非表示
  combo.Visibility = Visibility.Collapsed;
  m_1.IsSelected = true; // 会議室の指定を初期化
}
private void Button_Click(object sender, RoutedEventArgs e)
{ //ボタンがクリックされた場合は入力内容を取得してダイアログ表示
  string date,time = "",room;
  if (am.IsChecked == true) //RadioButtonのbool値を取得し条件分岐
    { time = am.Content.ToString(); }
  if (pm.IsChecked == true)
    { time = pm.Content.ToString(); }
  if (all.IsChecked == true)
    { time = all.Content.ToString(); }
  room = ((ComboBoxItem)combo.SelectedItem).Content.ToString();// コンボボックスの選択値を取得
  date = dtp.SelectedDate.ToString(); //日付を変数に代入
  MessageBox.Show( "日付 : "+ date + "\n時間 : " + time + "\n" + room + "を予約しました");
}
サンプルコードで値の受け渡しが発生したコントロール・プロパティについて、以下の表に示します。
| メソッド | プロパティ | 値 | 概要 | 
| cb_Checked | combo.Visibility | Collapsed | コンボボックスの表示・非表示の切替 | 
| cb_UnChecked | combo.Visibility | Visible | 同上 | 
| m_1.IsSelected | True | コンボボックスのアイテムの選択状態を設定 | |
| Button_Click | am.Checked | ラジオボタンのチェック状態を表すbool値を取得(pm、allも同様) | |
| am.Content | ラジオボタンの表示文字列の内容を取得し文字列として変数に代入(pm、allも同様) | ||
| ((ComboBoxItem)combo .SelectedItem).Content | コンボボックスの選択されたアイテムを取得し、表示文字列を取得 | ||
| dtp.SelectedDate | DatePickerで選択された日付を取得 | 
サンプルでは、コントロール名の後に.(ピリオド)とプロパティ名を続けることで、コントロールのプロパティを直接読み書きしています。
 プロパティ名を引数に取るGetValue/SetValueメソッドを使うことで、各コントロールのプロパティを取得/設定することもできます。通常のプロパティについては、サンプルで示したように直接コントロールのプロパティを操作する方法で十分ですが、添付プロパティ(Canvas.LeftやGrid.Rowなど、親コントロールで定義されるものの、値は子で指定するプロパティ)については、GetValue/SetValueメソッドで取得/設定します。
 さらに、HtmlPage.Document.GetElementByIdメソッドなどを使用することで、Silverlight 2を呼び出したHTMLのDOM要素にアクセスすることもできます。ASP.NETでホスティングしている場合には、DOM経由で値の受け渡しを行うこともできます。
では本サンプルを実行してみましょう。先ほどのサンプルを編集していますので、アカウント情報の入力など途中までは同じ動作です。遷移後の画面が会議室予約画面になっているでしょうか。各コントロールからデータを入力し、決定ボタンを押して、メッセージボックスが表示されれば成功です。
残念ながらSilverlight 2は現在、入力値検証(バリデーション)の機能をサポートしていません。業務アプリでは多用される機能ですが、現段階では入力値検証用にコードを書いて対応するしかないようです。早い段階でのサポートが望まれます。
まとめ
今回は、Silverlightのコントロールが業務アプリケーションでどのように扱えるかという観点から記事をお届けしました。あくまで基本的なコントロールの利用法でしたので、ASP.NET AJAXなど既存技術でも可能な実装との大きな差は意識できなかったかもしれません。
とはいえ、コントロールを配置して値を取得、設定するといった範囲において、Windows FormsやWPFとあまり変わらない感覚で、しかもC#やVBなど、自分が慣れ親しんだ言語で実装できるというのは開発者にとってRIA開発の敷居を下げるものとなります。また、UIデザインにおいてExpression Blendの強力な編集機能のサポートを受けられる、というメリットも大きいでしょう。
次回以降はいよいよSilverlight特有の機能であるアニメーションやデータバインディングを扱っていきます。次回をお楽しみに。
Silverlight Toolkitの最新リリースとしてSilverlight Toolkit December 2008が利用できるようになりました。CodePlexからダウンロードできます。
Silverlight Toolkit December 2008にはいくつかのStable版(品質面において、より安定したバージョン)コントロールやPreview版(同じく品質面において、アルファ版的な位置づけのバージョン)コントロール、そして幾つかのテーマ(コントロールのスタイルのテンプレート)が追加されました。追加されたコントロールやテーマの詳細は、公式サイトのサンプルをご覧ください。

 
              
               
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                          
                           
                              
                               
                              
                               
                              
                               
                              
                               
                              
                               
                      
                     
                      
                     
                      
                     
                      
                     
                      
                     
                      
                     
                      
                     
															
														 
															
														.png) 
     
     
     
     
     
													 
													 
													 
													 
													 
										
									



 
                     
                    
