WCF RIA Services:データ追加
WCF RIA Services 「らしい」データの追加方法のサンプルが見つけられず、情報をまとめるのに時間がかかってしまいました。
とりあえず自分なりに納得いく方法として下記にまとめてみます。
何点かまだ気に入らないところがあるんですけどね。。。
Silverlight側にSilverlight子ウィンドウを追加します。
データソースウィンドウでPersonを詳細表示の状態にします。
idは自動的に追加される項目なので、下記のように[なし]の状態にします。
この状態で子ウィンドウにPersonデータソースをドラッグ アンド ドロップします。
必要な入力項目が追加されます。
personDomainDataSourceのAutoLoadプロパティをfalseにします。
子ウィンドウのコードを以下のように修正します。
修正箇所はコメントを入れているあたりです。
————————————————————————————————
using System.Windows;
using System.Windows.Controls;
using SilverlightApplication10.Web;
namespace SilverlightApplication10
{
public partial class ChildWindow1 : ChildWindow
{
// データ保持のための変数
Person p = null;
public ChildWindow1()
{
InitializeComponent();
// 新規Personインスタンスの作成/追加と入力欄への関連づけ
p = new Person();
((DomainService1)personDomainDataSource.DomainContext).Persons.Add(p);
grid1.DataContext = p;
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
// データの検証および追加
personDomainDataSource.SubmitChanges();
if (!p.HasValidationErrors)
this.DialogResult = true;
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
}
private void personDomainDataSource_LoadedData(object sender, LoadedDataEventArgs e)
{
if (e.HasError)
{
System.Windows.MessageBox.Show(e.Error.ToString(), "Load Error", System.Windows.MessageBoxButton.OK);
e.MarkErrorAsHandled();
}
}
}
}
————————————————————————————————
MainPage.xamlに「追加」ボタンを追加します。
このボタンは「再取得」ボタンと同じように、データを更新しているときは使えないようにしたいと思います。
そのため、IsEnabledプロパティにソースとして「ElementName」-「PersonDomainDataSource」、パスとして「CanLoad」を設定します。
「追加」ボタンをダブルクリックし、以下のプログラムを記述します。
————————————————————————————————
private void button4_Click(object sender, RoutedEventArgs e)
{
// 子ウィンドウのインスタンスを生成
ChildWindow1 w = new ChildWindow1();
// 子ウィンドウを閉じたときにデータを読み直し、最終ページを表示するよう設定
w.Closed += (s, ev) =>
{
if (w.DialogResult == true)
{
personDomainDataSource.Load();
dataPager1.PageIndex = dataPager1.PageCount;
}
};
// 子ウィンドウの表示
w.Show();
}
————————————————————————————————
なお、PersonCheck.shared.csの内容を以下のように変更しておきます。
mailの値が空文字でもnullでもエラーになるようにしています。
また、エラー時のエラー設定項目としてageとmailの項目を指定しています。
————————————————————————————————
using System.ComponentModel.DataAnnotations;
namespace SilverlightApplication10.Web
{
public class PersonCheck
{
public static ValidationResult CheckAge_Mail(Person p)
{
if (p.age >= 20 && (p.mail == string.Empty || p.mail == null))
return new ValidationResult("成人はメールアドレス必須です", new string[] {"age", "mail"});
return ValidationResult.Success;
}
}
}
————————————————————————————————
これで動作のチェックができるようになりますが、気をつけないといけないのは、通常のデバッグ開始を実行してしまうと、検証のチェックにひっかかったときにエラーが発生したことを検知して動作が止まってしまうことです。
必ず「デバッグなしで開始」を実行します。
下図のように追加データの検証が行われます。
なお、上記の動作確認を行っていると、どうもクライアント側だけで検証できずにサーバ上での検証が走っているように思われます。
逆に考えると、サーバ上で検証のプログラムを記述すると、特になにもしなくてもクライアント側にサーバ上で発生した検証エラーを伝えられることがわかります。
検証エラーがでなければ、データを正常に追加することができます。
データを追加したあと、最終ページを表示するようにプログラムを記述しているつもりですが、どうも本来ページが増えるはずの動作のときに最終ページの1つ前のページしか表示されない、という状態になっています。
その点解消する方法がないか、調査は続けたいと思います。
WCF RIA Services:データ検証
WCF RIA Servicesでは、必須項目/範囲チェック/正規表現チェックといったデータの検証はメタデータクラスに属性を設定するだけで可能になります。
DomainServiceクラスを追加した際、同時に作成されるメタデータクラスに下記のように属性を設定してみます。
———————————————————————————————–
[MetadataTypeAttribute(typeof(Person.PersonMetadata))]
public partial class Person
{
internal sealed class PersonMetadata
{
private PersonMetadata()
{
}
[Display(Name = "年齢", Order = 2)]
[Range(0, 120, ErrorMessage = "年齢に誤りがあります")]
public int age { get; set; }
[Display(Name="ユーザID", Order=0)]
public int id { get; set; }
[Display(Name = "メールアドレス", Order = 3)]
[RegularExpression(@"\w+([-+.’]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "正しいメールアドレスを入力してください")]
public string mail { get; set; }
[Display(Name = "備考", Order = 4)]
public string memo { get; set; }
[Display(Name = "名前", Order = 1)]
[Required(ErrorMessage = "名前は必須項目です")]
public string name { get; set; }
}
}
———————————————————————————————–
この変更を行って実行すると、下記のようにデータの検証が行われます。
このとき「更新」ボタンが有効になっています。
で、このまま押してみると、、、画面が真っ白になってエラーとなってしまいます。
ただ、これはデバッグ実行をしているときのエラー制御が通常実行時と異なるために発生する現象のようです。
Ctrl+F5 を押して、デバッグなしで実行すると、「更新」ボタンを押しても何も起きないことを確認することができます。
さて、カスタムのデータ検証も追加してみましょう。そのためには、まずカスタム検証のメソッドを追加するクラスを作成します。
PersonCheck.shared.csというようにクラス名にsharedという名前を追加したファイルを作成します。
このようにファイル名にsharedをつけることで、クライアント側に自動的にこのファイルが追加されるようになります。
ファイルの中は下記のように記述します。
———————————————————————————————–
using System.ComponentModel.DataAnnotations;
namespace SilverlightApplication10.Web
{
public class PersonCheck
{
public static ValidationResult CheckAge_Mail(Person p)
{
if (p.age >= 20 && p.mail == string.Empty)
return new ValidationResult("成人はメールアドレス必須です");
return ValidationResult.Success;
}
}
}
———————————————————————————————–
メタデータクラスのPersonMetadataクラスにこのカスタム検証を使用するよう、以下の属性を追加します。
[MetadataTypeAttribute(typeof(Person.PersonMetadata))]
これで、年齢が20歳以上の場合でメールアドレスの入力がない場合にエラーが表示されるようになります。
WCF RIA Services:データ更新/キャンセル/再取得
WCF RIA Servicesで作成したサンプルはデフォルトでDataGird上でのデータの修正が可能です。
ただ、DataPagerを利用してページングを行っている場合、データを修正すると下図のようにページ番号がグレーアウトし、ページの移動ができなくなります。
この状態を解消し、ページの移動を可能にするには、データの修正をキャンセルするか、データベースにたいして修正内容を更新する必要があります。
キャンセルボタンと更新ボタンを追加します。
キャンセルボタンのCommandプロパティの下図のボタンをクリックし、「データバインドの適用」を選択します。
表示されるダイアログ上でソースとして「ElementName」-「PersonDomainDataSource」を選択します。
パスとして「RejectChangesCommand」を選択します。
更新ボタンは同様にCommandプロパティにソースとして「ElementName」-「PersonDomainDataSource」、パスとして「SubmitChangesCommand」を設定します。
この状態でデバッグを実行すると、アプリケーションを開始した時点ではキャンセルボタン、更新ボタンともに実行できない状態になっています。
データを修正すると、キャンセルボタン、更新ボタンが有効になります。
キャンセルボタンを押すと、修正内容が破棄され、ページの移動が可能になります。
更新ボタンを押すと、修正内容がデータベースに反映され、ページの移動が可能になります。
これで普通にデータ更新が可能になるのですが、いろいろと試していると他からデータが更新された場合、その内容が反映されないことがわかりました。
アプリケーションを実行し、Silverlight上からuser1のデータを修正します。
更新ボタンを押す前にデータベース上のuser2のデータを修正します。
この状態で更新ボタンを押すと、user1のデータは正しく書き換えられますが、user2の変更はSilverlight側には適用されません。
データベース上の最新状態をSilverlight側に反映させるには、データを再取得するしか方法がなさそうです。
再取得ボタンを追加し、Commandプロパティにソースとして「ElementName」-「PersonDomainDataSource」、パスとして「LoadCommand」を設定します。
これで大丈夫、、、と思ったのですが、実行してもSilverlight側にはデータベースで直接修正した内容がやっぱり反映されません。
いろいろ調べてみると、どうやらLoadBehaviorを変更する必要がありそうです。
この変更のタイミングとして、PersonDomainDataSourceのLoad時(LodingDataイベント)が使えるようです。
まずドキュメントアウトラインからDomainDataSourceを選択します。
PersonDomainDataSourceのイベントからLoadingDataをダブルクリックし、イベント発生時のメソッドを追加します。
personDomainDataSource_LoadingDataメソッド内で、LoadBehaviorの設定を変更します。
この設定の変更をすることで、はじめてSilverlight側でデータを再取得した際にデータベース上の修正内容が反映されるようになります。
米国TechEdのセッションが公開されてます
アメリカで行われているTechEdのセッションの情報が公開されています。
去年までだとMIXはともかくTechEdは非公開だったよーな。。。
とりあえずビデオが公開されてますね。
ダウンロードもできます。
スライドも落とせるようなリンクがあるのでもしかするとそちらも後から公開されるのかな?
しかしほんと、MSさんって太っ腹。
WCF RIA Services:レイアウトの設定
WCF RIA Servicesというより、VS2010(VWD2010)の機能の説明になってますが。
まず、MainPageに追加しているDataGridのColumnsプロパティのボタンをクリックし、Columnsのコレクションエディターを表示します。
ここですべてのDataGridTextColumnのWidthプロパティをAutoに設定します。
次にDataGridのWidthプロパティとHeightプロパティをAutoに設定します。
画面上の表示領域外側の薄く青い部分をクリックすることでGridを縦に分割します。
このとき、DataGridの下端に合わせるようにします。
その後、マウスをGridの高さの表示のあたりにポイントすることで設定値のガイドが表示されるので、ここで上部のGirdの列の高さをAutoに設定します。
同様にして、Gridを横に分割し、幅をAutoに設定します。
DataPagerのWidthをAutoに、HorizontalAlignmentをStretchに、Marginを0に設定します。
ここでデバッグ実行すると、DataGridとDataPagerがきれいに揃って表示されることが確認できます。