昨日に引き続いて、本日は、クライアントアプリケーション(UI)側の簡単なアーキテクチャ解説をします。
Navigation Framework の利用
本ソリューションサンプルでは、Silverlight アプリケーションプロジェクトのテンプレートとして 「Silverlight Business Application」を利用しています。これは、Navigation Frameworkを搭載しています。Tech・EdのT6-401等では、このテンプレートや、「Navigationアプリケーション」を選択していませんでしたが、実際のプロトタイピングでは、このフレームワークを使った方が便利な場合も多いですので、こちらもぜひ使ってみてください。(ちなみに、Tech・Ed 2009では、Silverlight 3 + 「Business Application」テンプレートで開発デモを行いました)
これにより、URL による Silverlight ページへのアクセスが可能となっています。
① URL マッピングの利用
Navigation Framework のURLマッピング機能を利用することにより、各ページへのアクセスのURLを容易にカスタマイズすることが可能となっています。
URL マッピングのサンプルは以下の通りです。
7行目の
<uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
という箇所に注目してください。
サンプル:\MSStoreSample\ MSStoreSample \MainPage.xaml
<navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}" Source="/Home" Navigated="ContentFrame_Navigated" NavigationFailed="ContentFrame_NavigationFailed"> <navigation:Frame.UriMapper> <uriMapper:UriMapper> <uriMapper:UriMapping Uri="/{pageName}/{id}" MappedUri="/Views/{pageName}.xaml?id={id}" /> <uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/> <uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/> </uriMapper:UriMapper> </navigation:Frame.UriMapper> </navigation:Frame>
URL マッピングを利用した画面遷移のサンプルは以下の通りです。
サンプル:\MSStoreSample\ MSStoreSample \Views/Home.xaml.cs
private void productListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { DefaultColorProducts selectedProduct = productListBox.SelectedItem as DefaultColorProducts; NavigationService.Navigate(new Uri(String.Format("/Product/{0}", selectedProduct.ProductId), UriKind.RelativeOrAbsolute)); }
やはり4行目の、
NavigationService.Navigate(new Uri(String.Format("/Product/{0}", selectedProduct.ProductId), UriKind.RelativeOrAbsolute));
という箇所に注目してください。ここで下記のようなURLを指定することにより、
http://localhost:8033/MSStoreSample.Web/#/Product/9ea8dafc-1940-4eaa-a30e-4b18e54f5941
このような下記URLに変換されて実行されます。
http://localhost:8033/MSStoreSample.Web/#/Views/Product.xaml/?id=9ea8dafc-1940-4eaa-a30e-4b18e54f5941
なお、以前のエントリで、「Navigation Application」テンプレート用のStyleを紹介しましたので、こちらも合わせてご利用ご検討ください。
*但し、日本語Visual Studioでこれらのテンプレートを適用した場合、エンコーディングがANSIになってしまうことがあります。その場合にはビルドエラーが出ますので、メモ帳等で、直接対象となる*.xamlファイルを開いて、UTF-8で上書き保存してください。
本ソリューションサンプルでは、Silverlight Toolkit で提供されている、様々なコントロールを利用することにより、以下のUI機能を実現しています。
① WrapPanel の利用
WrapPanle コントロールを、ItemsPanelTemplate として利用することにより、折り返し可能なリストボックスを実現しています。
サンプル:\MSStoreSample\ MSStoreSample\Views/Home.xaml
<navigation:Page.Resources> <ItemsPanelTemplate x:Key="HorizonalWrapPanel"> <controlsToolkit:WrapPanel Orientation="Horizontal" /> </ItemsPanelTemplate>
次に、バインディングの実装について、です。
① 双方向バインドの利用
ソリューションサンプルでは、Siliverlight で提供されている双方向バインド機能を利用しています。
WCF RIA Services を利用する場合、実はDomain Service と、クライアント側で共有(コピー)されるエンティティはすでに INotifyPropertyChanged インタフェースを実装しています。したがって、UI(XAML) にてバインディングを設定することで、双方向バインドを実現することができます。これは別途続編のところでまたご紹介できればと思います。
サンプル: \MSStoreSample\MSStoreSample\Views\Product.xaml
<TextBox x:Name="quantityTextBox" Grid.Row="5" Grid.Column="1" Margin="8,8,0,8" HorizontalAlignment="Left" VerticalAlignment="Center" Width="60" Height="24" FontSize="14" Text="{Binding Quantity, Mode=TwoWay}" />
Silverlight アプリケーションでは、上記バインディングの機能を利用して入力検証を行います。Tech・EdのT6-401のセッションでもご紹介しました通り、WCF RIA Services を利用する場合、Domain Service で定義するエンティティのメタデータクラスのプロパティ宣言に対して、属性を付与することにより、エンティティ検証処理を実装することができます。
エンティティメタデータの実装:
サンプル:\MSStoreSample\MSStoreSample.Web\Services\MSStoreSampleDomainService.metadata.cs
[MetadataTypeAttribute(typeof(BasketItems.BasketItemsMetadata))] public partial class BasketItems { // This class allows you to attach custom attributes to properties // of the BasketItems class. // // For example, the following marks the Xyz property as a // required property and specifies the format for valid values: // [Required] // [RegularExpression("[A-Z][A-Za-z0-9]*")] // [StringLength(32)] // public string Xyz { get; set; } internal sealed class BasketItemsMetadata { // Metadata classes are not meant to be instantiated. private BasketItemsMetadata() { } … [Include] public Products Products { get; set; } [Required] [Range(1, 99, ErrorMessage = "数量は 1 - 99 の間で入力してください。")] public Nullable<int> Quantity { get; set; } public string Size { get; set; } public string Style { get; set; } public Nullable<decimal> SubTotal { get; set; } } }
27行目の[Required]、[Range]あたりに注目してください。解説は、T6-401解説前半部分である、こちらもご参考に。
XAML での入力検証の定義: サンプル: \MSStoreSample\MSStoreSample\Views\Product.xaml
<TextBox x:Name="quantityTextBox" Grid.Row="5" Grid.Column="1" Margin="8,8,0,8" HorizontalAlignment="Left" VerticalAlignment="Center" Width="60" Height="24" FontSize="14" Text="{Binding Quantity, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" />
上記の宣言(6行目に注目)により、下記のような表示となります。
本ソリューションサンプルでは Silverlight Business Application テンプレートに含まれる標準の認証機能を利用しています。標準の認証機能は ASP.NET Membership Provider をベースに実装されていますが、独自に拡張を行うことも可能です。
以上です。次回は、第3回から第11回までのポイント解説をお送りします。
鈴木 章太郎