REMIX09 Tokyo、B-2セッションデモ・解説(4)
今までのは確かにいくつかのリッチなデータ表示の仕方でした。しかし次に、ビジネスアプリケーションは、データの更新もうまく行わなければなりません。そのやり方を学びましょう。
最初に、すべてのXAMLを下記のものに置き換えます。これはマスター・ディテールのビューとなっています。
<Home.xaml( LayoutRoot以下を表示)>
<Grid x:Name="LayoutRoot">
<ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}" >
<StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">
<TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}"
Text="Home"/>
<TextBlock x:Name="ContentText" Style="{StaticResource ContentTextStyle}"
Text="特別従業員派遣要員名簿"/>
<!--DomainDataSource-->
<riaControls:DomainDataSource x:Name="dds"
AutoLoad="True"
QueryName="GetSuperEmployeesQuery"
LoadSize="20">
<!--DomainDataSource.DomainContext-->
<riaControls:DomainDataSource.DomainContext>
<App:SuperEmployeeDomainContext/>
</riaControls:DomainDataSource.DomainContext>
<!--GroupDescriptors-->
<riaControls:DomainDataSource.GroupDescriptors>
<datagroup:GroupDescriptor PropertyPath="Publishers" />
</riaControls:DomainDataSource.GroupDescriptors>
<!--FilterDescriptors-->
<riaControls:DomainDataSource.FilterDescriptors>
<datagroup:FilterDescriptorCollection>
<datagroup:FilterDescriptor PropertyPath="Origin"
Operator="StartsWith">
<datagroup:ControlParameter PropertyName="Text"
RefreshEventName="TextChanged"
ControlName="originFilterBox">
</datagroup:ControlParameter>
</datagroup:FilterDescriptor>
</datagroup:FilterDescriptorCollection>
</riaControls:DomainDataSource.FilterDescriptors>
</riaControls:DomainDataSource>
<StackPanel Style="{StaticResource DetailsStackPanelStyle}">
<activity:Activity IsActive="{Binding IsBusy, ElementName=dds}">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<TextBlock Text="Origin: " />
<input:AutoCompleteBox x:Name="originFilterBox" Width="338" Height="30"
ValueMemberBinding="{Binding Name}"
ItemTemplate="{StaticResource OriginsDataTemplate}" />
</StackPanel>
<data:DataGrid x:Name="dataGrid1" Height="380" Width="380"
IsReadOnly="True" AutoGenerateColumns="False"
HorizontalAlignment="Left"
SelectionChanged="dataGrid1_SelectionChanged"
HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Data, ElementName=dds}"
>
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<data:DataGridTextColumn Header="Employee ID" Binding="{Binding EmployeeID}" />
<data:DataGridTextColumn Header="Origin" Binding="{Binding Origin}" />
</data:DataGrid.Columns>
</data:DataGrid>
<data:DataPager PageSize="13" Width="379"
HorizontalAlignment="Left"
Source="{Binding Data, ElementName=dds}"
Margin="0,0.2,0,0" />
<!--Submit Button-->
<StackPanel Orientation="Horizontal" Margin="0,5,0,0">
<Button Content="Submit" Width="105" Height="28"
Click="SubmitButton_Click" />
<!--Add New Button ☆ -->
</StackPanel>
</StackPanel>
</activity:Activity>
<StackPanel Margin="35,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Height="498" >
<dataControls:DataForm x:Name="dataForm1" Height="393" Width="331"
VerticalAlignment="Top"
Header="Product Details"
CurrentItem="{Binding SelectedItem, ElementName=dataGrid1}"
HorizontalAlignment="Left" >
<dataControls:DataForm.EditTemplate>
<DataTemplate>
<StackPanel>
<dataControls:DataField>
<TextBox Text="{Binding Name, Mode=TwoWay}" />
</dataControls:DataField>
<dataControls:DataField>
<TextBox Text="{Binding EmployeeID, Mode=TwoWay}" />
</dataControls:DataField>
<dataControls:DataField>
<TextBox Text="{Binding Origin, Mode=TwoWay}" />
</dataControls:DataField>
<dataControls:DataField>
<TextBox Text="{Binding Sites, Mode=TwoWay}" />
</dataControls:DataField>
<dataControls:DataField>
<TextBox Text="{Binding Gender, Mode=TwoWay}" />
</dataControls:DataField>
<dataControls:DataField>
<TextBox Text="{Binding Publishers, Mode=TwoWay}" />
</dataControls:DataField>
<dataControls:DataField>
<controls:DatePicker Text="{Binding LastEdit, Mode=OneWay}"></controls:DatePicker>
</dataControls:DataField>
<dataControls:DataField>
<TextBox Text="{Binding Issues, Mode=TwoWay}" />
</dataControls:DataField>
</StackPanel>
</DataTemplate>
</dataControls:DataForm.EditTemplate>
</dataControls:DataForm>
<!--Permalink -->
<TextBlock Text="PermaLink:"></TextBlock>
<TextBox x:Name="PermalinkTextBox" Width="400" Height="25" TextWrapping="NoWrap" Foreground="#FFB4B4B4" />
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
</Grid>
途中の ☆ の個所までは、これまで作ってきたものに似ています。 しかしその次の行以降は、DataForm コントロールを追加し、特定のエンティティに対して大変見やすく編集しやすいものになっています。
F5を押して実行します。まさにこれにより、伝統的なマスター・ディテールのシナリオが実現できます。
ここで注目すべきは、アイテムを更新すると”Dirty”としてマークされます( ※ )。
これが意味しているのは、それらの更新データは、再度サーバーに送信される必要があるということです。多くのアイテムを編集できますが、編集を元に戻すと、”Dirty"フラグ( ※ )は消えます。 それでは、Submit ボタンのイベントハンドラを実装しましょう。
<SubmitButton_Click >
private void SubmitButton_Click(object sender, RoutedEventArgs e)
{
dataForm1.CommitEdit();
dds.SubmitChanges();
}
最初に、現在編集中のアイテムをコミットする必要があります。その後、更新を送信します。これにより、差分が更新されてサーバーに返送され、更新メソッドが呼ばれます。”Dirty"マークが消えたのを確認してください。
データ更新におけるバリデーション
確かにかなり格好良くなりました。しかし、データバリデーションはどうなのでしょう? 実はこの点も“最初から”Type Level のバリデーションは作成されています(当該フィールドがもしIntとタイプ定義されていると、String型のデータを入れるとエラーになります)。それでは、もう少し追加ができないか見てみましょう。
これを行うには、サーバー側にある、SuperEmployeeDomainService.metadata.csを編集する必要があります。 サーバー側でこれらのバリデーションを行うことは極めて重要です。それにより当該システムにおいて、すべてのバリデーションが、いったん素晴らしいUX で実行され、次いでサーバー側で実行されることにより、データの信頼性が保障されるのです。 更新メソッドがDomainService上で呼ばれるまでに、すべてのバリデーションがなされている必要があります。
下記に、いくつかの追加可能なバリデーションを列挙します。
<SuperEmployeeDomainService.metadata.cs>
・・・
[ReadOnly(true)]
public int EmployeeID;
public EntityState EntityState;
[RegularExpression("^(?:m|M|male|Male|f|F|female|Female)$",
ErrorMessage = "性別は 'Male' か 'Female' である必要があります。 ")]
public string Gender;
[Range(0, 10000,
ErrorMessage = "Issuesは0 から1000の間で入力してください。 ")]
public Nullable<int> Issues;
public Nullable<DateTime> LastEdit;
[Required]
[StringLength(100)]
public string Name;
追加したら、リビルドして、アプリケーションを実行すると、素晴らしいバリデーションがUIとMidティアに追加されています。
いかがでしょうか?今回のものは、データの更新とバリデーションの追加でしたが、それではデータの新規追加はどのようにすればいいでしょうか?次回は、この目的を中心に、Silverlight 3 に新しく追加されたテンプレートである、ChildWindowを見てみましょう。