それでは各メニューのコンテンツ作成に入っていこう。取りあえずユーザーを登録できなければ何も始められない。そこで、[ユーザー登録]メニューのコンテンツから開発する。
●コンテンツ作成の準備
[ソリューション エクスプローラー]から[ユーザー登録]コンテンツ(=ContetUserEntry.xamlファイル。前回解説したように実体はユーザー・コントロール)をダブルクリックで開いて、前回、切り替え識別用に追加したTextBlockコントロールを削除しよう(=WPFデザイナ上の該当コントロールをクリックにより選択して[Delete]キーを押す)。
●「詳細」コントロールの作成
次に、何もなくなったユーザー・コントロールのGridパネル上に「詳細」(=項目名を示すLabelコントロール+入力欄となるTextBoxコントロールなどの組み合わせを1行として、入力項目の数だけ行が並べられたGridパネル)を追加する。
この方法は「特集:初めてのWPF/Silverlightデータグリッド開発」で説明しているので、以下では重要なポイント以外の詳細な説明は割愛させていただく。
○「詳細」コントロールの追加
簡単に説明しておくと、作成したデータセットは(その階層構造がツリー形式で)[データ ソース]ウィンドウに表示されるので、データセット項目の直下にある「User」データテーブル項目の右端にある[▼]ボタンからWPFデータ・バインド・コントロールとして[詳細]を選択し、各列項目の右端にある[▼]ボタンからそれぞれ下記の表のとおりのコントロールを選択する。
列名 | コントロール |
---|---|
ID | [なし] |
Name | TextBox |
DutyPerson | CheckBox |
Order | [なし] |
Userデータテーブルの各列に割り当てるコントロール ※Order列は、OrderテーブルのUser_ID列(=外部キー)が、UserデータテーブルのID列(=親キー)を参照しているために表示されている。 |
後は、その「User」データテーブル項目を、WPFデザイナのデザイン・サーフェイス上にドラッグ&ドロップする(次の画面を参照)。
追加された「詳細」(=Gridパネル)の左上に表示されている[+]部分の右クリック・メニューから[レイアウトのリセット]−[すべて]を実行すると、「詳細」がユーザー・コントロール全体に広がる。
○Gridパネルの既存行の前後への、行の追加
この状態でコードを少し記述すれば、既存のUserデータを表示できる。しかし、ここで行いたいのは、(表示ではなく)むしろ「ユーザー登録」の処理だ。これを実現するために、Gridパネルにもう1行追加して、その行に[登録]ボタンを配置することにしよう。
前回はグリッド線を引く方法を説明したが、今回は既存行の前後に行を追加する方法を説明しよう。
ここでは[Duty Person]チェックボックス行の下に1行追加する。これには、WPFデザイナでそのチェックボックスを右クリックし、表示されるコンテキスト・メニューから[グリッド行]−[後ろへ挿入]を実行すればよい(当然、上に1行追加する場合は、[前へ挿入]を実行)。
追加された行の2列目に[ツールボックス]からButtonコントロール(名前:ButtonAdd、Contentプロパティ:登録)をドラッグ&ドロップしよう。
Girdパネルの目的のセルにコントロールを適切に追加するには、少しコツが必要だ(これについて「前編:【コラム】Gridパネルのセルにコントロールを追加する方法」を参照してほしい。なお、このコラムは前編公開後の2010年12月21日に追記したもの)。
ドラッグ&ドロップした結果は次のとおり。
そのほか、Gridパネル自体のMarginプロパティの設定や、Gridパネルの列や行のサイズなど、見た目に関する微調整が必要だ。また、「詳細」で追加された各行のLabelコントロールのContentプロパティに適切な項目名を設定する必要がある。これらの調整作業は、今回の本旨からは外れる内容なので割愛する(これらの作業については、前編が参考になるだろう)。
○新規データ行の追加処理(=データテーブルによるDBアクセス)
次に、[登録]ボタンがクリックされた際に、Userテーブルに新しいユーザー(=新規行)を登録する処理を実装しよう。
WPFデザイナ上の[登録]ボタンをダブルクリックして、Clickイベント・ハンドラを追加すると、XAMLファイルのコードビハインドであるContetUserEntry.xaml.cs/.vbファイルが自動的に開かれる。このファイルには、(次の画面からも分かるように)UserControl_LoadedメソッドとButtonAdd_Clickメソッドが生成されている。UserControl_Loadedメソッド内はコメント・アウトされているが、先ほどの「詳細」を追加したときに自動生成されたものだ。
このコードを次のように書き換える。
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using ObentoApp.ObentoDataSetTableAdapters;
……省略……
private ObentoDataSet myDS; // データセット
private UserTableAdapter myTA; // Userテーブルアダプタ
private CollectionViewSource myCVS; // コレクションビューソース
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
// デザイン時にはデータは読み込まれません
if (!DesignerProperties.GetIsInDesignMode(this))
{
// XAMLファイル側で作成されたデータセットを取得
myDS = ((ObentoDataSet)(this.FindResource("obentoDataSet")));
// Userテーブルアダプタで、データセットにUserデータを読み込む
myTA = new UserTableAdapter();
try
{
myTA.Fill(myDS.User);
}
catch (Exception ex)
{
MessageBox.Show("ユーザー・データの読み込みでエラーが発生しました。\n" + ex.Message);
return;
}
// XAMLファイル側で作成されたコレクションビューソースを取得
myCVS = (CollectionViewSource)this.Resources["userViewSource"];
// コレクションビューソース内の新規行に移動
myCVS.View.MoveCurrentTo(null);
}
}
private void ButtonAdd_Click(object sender, RoutedEventArgs e)
{
// ユーザー名を取得
string name = nameTextBox.Text.Trim();
if (String.IsNullOrEmpty(name))
{
MessageBox.Show("ユーザー名を入力してください。");
return;
}
// お弁当当番かどうかを取得(Nullable型の判定で??演算子を使用)
bool dutyPerson = dutyPersonCheckBox.IsChecked ?? false;
// データセット内のUserデータテーブルに新規行を追加
myDS.User.AddUserRow(name, dutyPerson);
// Userテーブルアダプタで、Userデータをデータベースに書き込む
try
{
myTA.Update(myDS.User);
}
catch (DBConcurrencyException de)
{
MessageBox.Show("登録に失敗しました。\n" + de.Message);
return;
}
catch (Exception ex)
{
MessageBox.Show("エラーが発生しました。\n" + ex.Message);
return;
}
// コレクションビューを更新
myCVS.View.Refresh();
// コレクションビューソース内の新規行に移動
myCVS.View.MoveCurrentTo(null);
}
……省略……
Imports System.ComponentModel
Imports ObentoApp.ObentoDataSetTableAdapters
……省略……
Private myDS As ObentoDataSet // データセット
Private myTA As UserTableAdapter // Userテーブルアダプタ
Private myCVS As CollectionViewSource // コレクションビューソース
Private Sub UserControl_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
// デザイン時にはデータは読み込まれません。
If Not (DesignerProperties.GetIsInDesignMode(Me)) Then
// XAMLファイル側で作成されたデータセットを取得
myDS = CType(Me.FindResource("ObentoDataSet"), ObentoDataSet)
// Userテーブルアダプタを生成
myTA = New UserTableAdapter()
// Userテーブルアダプタで、データセットにUserデータを読み込む
Try
myTA.Fill(myDS.User)
Catch ex As Exception
MessageBox.Show("ユーザー・データの読み込みでエラーが発生しました。" & vbLf & ex.Message)
Return
End Try
// XAMLファイル側で作成されたコレクションビューソースを取得
myCVS = CType(Me.Resources("UserViewSource"), CollectionViewSource)
// コレクションビューソース内の新規行に移動
myCVS.View.MoveCurrentTo(Nothing)
End If
End Sub
Private Sub ButtonAdd_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles ButtonAdd.Click
// ユーザー名を取得
Dim name As String = NameTextBox.Text.Trim()
If String.IsNullOrEmpty(name) Then
MessageBox.Show("ユーザー名を入力してください。")
Return
End If
// お弁当当番かどうかを取得(Nullable型の判定でIf演算子を使用)
Dim dutyPerson As Boolean = If(DutyPersonCheckBox.IsChecked, False)
// データセット内のUserデータテーブルに新規行を追加
myDS.User.AddUserRow(name, dutyPerson)
' Userテーブルアダプタで、Userデータをデータベースに書き込む
Try
myTA.Update(myDS.User)
Catch de As DBConcurrencyException
MessageBox.Show("登録に失敗しました。" & vbLf & de.Message)
Return
Catch ex As Exception
MessageBox.Show("エラーが発生しました。" & vbLf & ex.Message)
Return
End Try
// コレクションビューを更新
myCVS.View.Refresh()
// コレクションビューソース内の新規行に移動
myCVS.View.MoveCurrentTo(Nothing)
End Sub
……省略……
この状態でビルドしてアプリケーションを実行すると、ユーザーを登録できる。
次に、「詳細」で既存データを移動できるようにする(これにより既存データを修正/削除できるようになる)。また、各種リソースをアプリケーション全体で共有する。
Copyright© Digital Advantage Corp. All Rights Reserved.