Windows Presentation Foundation データ バインディング: パート 2
Shawn Wildermuth
2006 年 5 月
適用対象:
Microsoft Windows Presentation Foundation
概要:このシリーズのパート 2 では、XAML ベースのデータ バインディングを使用して Microsoft Windows Presentation Foundation プロジェクトでデータ操作を実行する方法を引き続き説明します。 (21ページ印刷)
内容
はじめに
データベース データへのバインド
ここはどこですか。
リファレンス
はじめに
コミュニティでノイズを発生させているWindows Presentation Foundation (WPF) の例のほとんどは、グラフィカル エンジンのシズルに関するものです。 ユーザー インターフェイス開発者の大半の仕事は、エンタープライズ開発の世界で日常的なデータ入力フォームを開発することです。 WPF には、問題を解決するためのソリューションがありますか? それは確かです...
データベース データへのバインド
この記事シリーズの最初の部分では、生のバインド構文について詳しく説明し、単純なオブジェクトを XAML オブジェクトにバインドする方法を調べました。 これはパズルの重要な部分ですが、ほとんどの状況では、実際の要件はデータベースに格納されているデータにバインドすることです。 ほとんどの場合、データベース データ (DataSets、DataTables、DataRows など) とカスタム ビジネス オブジェクトという 2 つの異なるシナリオでのバインドがサポートされています。
データベース データへのバインド
データベースは、現在でもほとんどの開発の中心であり、特にエンタープライズ開発です。 これを例示するために、ユーザーがデータベース内の従業員を参照できるようにする WPF ダイアログ ボックスの簡単な例を使用できます。 従業員の写真を含む少量の情報をブラウザーに表示できるようにしたいと考えています。 必要なすべての情報を含むテーブルを読み込む必要があります。 これを行うには、次のように、データベースからの情報を含む新しい DataTable を 作成します。
C#
DataTable theTable = new DataTable();
string connString =
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
string query = @"SELECT EmployeeID, FirstName, LastName, Title, HireDate, Photo
FROM Employees";
// Fill the Set with the data
using (SqlConnection conn = new SqlConnection(connString))
{
SqlDataAdapter da = new SqlDataAdapter(query, conn);
da.Fill(theTable);
}
Visual Basic .NET
Dim theTable As DataTable = New DataTable()
String connString =
ConfigurationManager.ConnectionStrings("Northwind").ConnectionString
String query = "SELECT EmployeeID, FirstName, LastName, Title, HireDate, Photo " + _
" FROM Employees"
' Fill the Set with the data
Using conn as New SqlConnection(connString))
Dim da As SqlDataAdapter = New SqlDataAdapter(query,conn)
da.Fill(theTable)
End Using
データを取得したら、それを使用して DataContext を設定し、XAML でバインドできるようにします。
C#
// Set the Data Context
DataContext = theTable;
Visual Basic .NET
' Set the Data Context
DataContext = theTable
データを取得してウィンドウに提供したので、XAML でデータ バインディングを実行できます。 ComboBox の Binding は、親の DataContext からデータを取得するようにバインドに指示するだけです (この場合、ウィンドウで DataContext が見つかるまでコントロール ツリーを上に移動します)。
<ComboBox Name="theCombo"
IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}"
... />
IsSynchronizedWithCurrentItem 属性は、選択範囲が変更されたときに、ウィンドウに関する限り"現在のアイテム" が変更される点で重要です。 これにより、現在の項目を変更するためにこのオブジェクトが使用されることを WPF エンジンに指示します。 この属性がないと、 DataContext 内の現在の項目は変更されないため、テキスト ボックスはリストの最初の項目に残っていると見なします。
コンボ ボックスに従業員の名前を表示するには、DataTable の FirstName と LastName を表示するバインドを ItemsTemplate に作成します。
<DataTemplate x:Key="EmployeeListTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding Path=LastName}" />
</StackPanel>
</DataTemplate>
次に、名前、役職、採用日を保持するテキスト ボックスを追加します。
<TextBlock Canvas.Top="5">First Name:</TextBlock>
<TextBox Canvas.Top="5" Text="{Binding Path=FirstName}" />
<TextBlock Canvas.Top="25">Last Name:</TextBlock>
<TextBox Canvas.Top="25" Text="{Binding Path=LastName}" />
<TextBlock Canvas.Top="45">Title:</TextBlock>
<TextBox Canvas.Top="45" Text="{Binding Path=Title}" />
<TextBlock Canvas.Top="65">Hire Date:</TextBlock>
<TextBox Canvas.Top="65" Text="{Binding Path=HireDate}" />
写真も必要なので、XAML に画像を追加する必要があります。
<Image Name="theImage" Canvas.Top="5" Canvas.Left="5" Width="75"/>
画像の唯一の問題は、画像への写真データの自動バインドがサポートされていないことです。 これを容易にするために、ComboBox の SelectionChanged イベントを処理して画像を埋めることができます。
<ComboBox Name="theCombo"
IsSynchronizedWithCurrentItem="True"
Width="200"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource EmployeeListTemplate}"
SelectionChanged="theCombo_OnSelectionChanged" />
コードでは、DataTable からイメージを読み込み、Image タグを埋めるために BitmapImage オブジェクトを作成する必要があります。 これは GDI+ からのビットマップ (System.Drawing) ではなく、WPF の新しい Bitmap オブジェクトであることに注意してください。
C#
// Handler to show the image
void theCombo_OnSelectionChanged(object sender, RoutedEventArgs e)
{
ShowPhoto();
}
// Shows the Photo for the currently selected item
void ShowPhoto()
{
object selected = theCombo.SelectedItem;
DataRow row = ((DataRowView)selected).Row;
// Get the raw bytes of the image
byte[] photoSource = (byte[])row["Photo"];
// Create the bitmap object
// NOTE: This is *not* a GDI+ Bitmap object
BitmapImage bitmap = new BitmapImage();
MemoryStream strm = new MemoryStream();
// Well-known work-around to make Northwind images work
int offset = 78;
strm.Write(photoSource, offset, photoSource.Length - offset);
// Read the image into the bitmap object
bitmap.BeginInit();
bitmap.StreamSource = strm;
bitmap.EndInit();
// Set the Image with the Bitmap
theImage.Source = bitmap;
}
Visual Basic .NET
' Handler to show the image
Sub theCombo_OnSelectionChanged(ByVal sender As Object, ByVal e As RoutedEventArgs)
ShowPhoto();
End Sub
// Shows the Photo for the currently selected item
Sub ShowPhoto()
Dim selected As Object = theCombo.SelectedItem
Dim row As DataRow = (CType(selected, DataRowView)).Row
' Get the raw bytes of the image
Dim photoSource() As Byte = CType(row("Photo"), Byte())
' Create the bitmap object
' NOTE: This is *not* a GDI+ Bitmap object
Dim bitmap As BitmapImage = New BitmapImage()
Dim strm As MemoryStream = New MemoryStream()
' Well-known work-around to make Northwind images work
Dim offset As Integer = 78
strm.Write(photoSource, offset, photoSource.Length - offset)
' Read the image into the bitmap object
bitmap.BeginInit()
bitmap.StreamSource = strm
bitmap.EndInit()
' Set the Image with the Bitmap
theImage.Source = bitmap
End Sub
ComboBox から SelectedItem を取得し、データを取得できるように DataRow に変換します。 次に、 Photo 列からバイト配列を取得します。 これは Northwind データベースに格納されている写真です。 メモリ内ストリームを使用して、写真のバイトを BitmapImage オブジェクトにストリーミングできます。 唯一の変更は、Northwind のイメージ ヘッダーの最初の 78 バイトをスキップするために一般的に使用される回避策です。これは、使用されなくなったためです。 ストリームをビットマップに読み込んだら、ソースとして Image オブジェクトに割り当てることができます。
データ バインディングが双方向であることを確認する必要があるため、現在の情報を表示するボタンを作成して、 DataRow に含まれていることを確認します。
C#
void SaveButton_OnClick(object sender, RoutedEventArgs e)
{
object selected = theCombo.SelectedItem;
DataRow row = ((DataRowView)selected).Row;
MessageBox.Show(string.Format("{0} {1} {2} - {3:d}",
row["Title"], row["FirstName"], row["LastName"], row["HireDate"]));
}
Visual Basic .NET
Sub SaveButton_OnClick(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim selected As Object = theCombo.SelectedItem
Dim row As DataRow = (CType(selected, DataRowView)).Row
MessageBox.Show(String.Format("{0} {1} {2} - {3:d}", _
row("Title"), row("FirstName"), row("LastName"), row("HireDate")))
End Sub
XAML ファイル全体は、次のようになります。
<Window x:Class="ExampleCS.EmployeeBrowser"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
Title="Employee Browser"
Loaded="OnLoaded"
Width="300"
Height="170"
WindowStartupLocation="CenterScreen"
>
<Window.Resources>
<DataTemplate x:Key="EmployeeListTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding Path=LastName}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Window.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="DarkGray" Offset="0" />
<GradientStop Color="White" Offset=".75" />
<GradientStop Color="DarkGray" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Window.Background>
<StackPanel Name="theStackPanel"
VerticalAlignment="Top">
<ComboBox Name="theCombo"
IsSynchronizedWithCurrentItem="True"
Width="200"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource EmployeeListTemplate}"
SelectionChanged="theCombo_OnSelectionChanged" />
<Canvas>
<Canvas.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Canvas.Left" Value="160" />
<Setter Property="Padding" Value="0" />
<Setter Property="Height" Value="18" />
<Setter Property="Width" Value="120" />
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Canvas.Left" Value="90" />
<Setter Property="Padding" Value="0" />
<Setter Property="Height" Value="18" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
</Canvas.Resources>
<Image Name="theImage" Canvas.Top="5" Canvas.Left="5" Width="75"/>
<TextBlock Canvas.Top="5">First Name:</TextBlock>
<TextBox Canvas.Top="5" Text="{Binding Path=FirstName}" />
<TextBlock Canvas.Top="25">Last Name:</TextBlock>
<TextBox Canvas.Top="25" Text="{Binding Path=LastName}" />
<TextBlock Canvas.Top="45">Title:</TextBlock>
<TextBox Canvas.Top="45" Text="{Binding Path=Title}" />
<TextBlock Canvas.Top="65">Hire Date:</TextBlock>
<TextBox Canvas.Top="65" Text="{Binding Path=HireDate}" />
<Button Canvas.Top="85" Canvas.Left="90" Width="190"
Name="SaveButton" Click="SaveButton_OnClick">Save</Button>
</Canvas>
</StackPanel>
</Window>
次に、ブラウザーを実行すると、図 1 に示すようなインターフェイスが得られます。
図 1. 従業員ブラウザー
この簡単な例はかなり簡単ですが、DataSet 内で関連する DataTable を使用している場合はどうでしょうか。 それが同じくらい簡単かどうかを見てみましょう。
関連する DataTable のバインド
従業員が営業担当者である注文を含むように Employee Browser を拡張しましょう。 これを行うには、注文情報を取得する必要があります。 これは、ユーザーを切り替えるたびに新しいクエリで行うことができますが、代わりに、Employee と共に DataSet にデータを読み込み、DataRelation を使用して 2 つの情報を関連付けてみましょう。
C#
DataSet theSet = new DataSet();
string connString = ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
string employeeQuery = @"
SELECT EmployeeID, FirstName, LastName, Title, HireDate, Photo
FROM Employees
";
string orderQuery = @"
SELECT o.OrderID, EmployeeID, CompanyName, OrderDate, SUM((UnitPrice * Quantity)* (1-Discount)) as OrderTotal
FROM Orders o
JOIN [Order Details] od on o.OrderID = od.OrderID
JOIN Customers c on c.CustomerID = o.CustomerID
GROUP BY o.OrderID, o.EmployeeID, o.OrderDate, CompanyName";
// Fill the Set with the data
using (SqlConnection conn = new SqlConnection(connString))
{
SqlDataAdapter da = new SqlDataAdapter(employeeQuery, conn);
da.Fill(theSet, "Employees");
da.SelectCommand.CommandText = orderQuery;
da.Fill(theSet, "Orders");
}
// Create the relationship
DataTable empTable = theSet.Tables["Employees"];
DataTable ordTable = theSet.Tables["Orders"];
theSet.Relations.Add("Emp2Ord",
empTable.Columns["EmployeeID"],
ordTable.Columns["EmployeeID"],
false);
// Set the Context of the Window to be the
// DataTable we've created
DataContext = empTable;
Visual Basic .NET
Dim theSet As DataSet = New DataSet()
Dim connString As String = _
ConfigurationManager.ConnectionStrings("Northwind").ConnectionString
String employeeQuery = _
"SELECT EmployeeID, FirstName, LastName, Title, HireDate, Photo " + _
" FROM Employees"
String orderQuery = _
"SELECT o.OrderID, EmployeeID, CompanyName, OrderDate, " + _
" SUM((UnitPrice * Quantity)* (1-Discount)) as OrderTotal " +
"FROM Orders o " +
"JOIN (Order Details) od on o.OrderID = od.OrderID " +
"JOIN Customers c on c.CustomerID = o.CustomerID " +
"GROUP BY o.OrderID, o.EmployeeID, o.OrderDate, CompanyName"
' Fill the Set with the data
Using conn as New SqlConnection(connString)
Dim da As SqlDataAdapter = New SqlDataAdapter(employeeQuery,conn)
da.Fill(theSet, "Employees")
da.SelectCommand.CommandText = orderQuery
da.Fill(theSet, "Orders")
End Using
' Create the relationship
Dim empTable As DataTable = theSet.Tables("Employees")
Dim ordTable As DataTable = theSet.Tables("Orders")
theSet.Relations.Add("Emp2Ord",
empTable.Columns("EmployeeID"),
ordTable.Columns("EmployeeID"),
False)
' Set the Context of the Window to be the
' DataTable we've created
DataContext = empTable
このコードでは、Employees と Orders という 2 つのテーブルを持つ DataSet を作成します。 これらのテーブルは、Emp2Ord と呼ばれる Relation を介して EmployeeID によって関連付けられます。 XAML の元のデータ バインディングが正常に動作するように、Employee DataTable にバインドすることもできます。 Windows フォームや ASP.NET データ バインディングと同様に、Relation の名前にバインドして、一連の関連レコードにバインドできます。
<ListBox Name="OrderList" Width="280" Height="200"
ItemsSource="{Binding Emp2Ord}"
ItemTemplate="{StaticResource OrderListTemplate}" />
このリスト ボックスでは、Employee Browser の残りの部分と同じ DataContext が引き続き使用されます。代わりに、リレーションシップを介してバインドを指定するだけです。 リスト ボックスを Relation にバインドすると、従業員コンボ ボックスの場合と同様に、 ItemTemplate の個々のフィールドにバインドできます。
<DataTemplate x:Key="OrderListTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Top" Width="100"
Text="{Binding Path=CompanyName}" />
<StackPanel>
<TextBlock Text="{Binding Path=OrderID}" />
<TextBlock Text="{Binding Path=OrderDate}" />
<TextBlock Text="{Binding Path=OrderTotal}" />
</StackPanel>
</StackPanel>
</DataTemplate>
この追加のデータ バインディングにより、図 2 に示すように、選択したユーザーにのみ関連する注文情報のリスト ボックスが表示されます。
図 2. 改善された従業員向けブラウザー
これにより、単純な四角形のデータよりも複雑なデータにバインドできます。 多くの組織では、カスタム .NET 型 (またはビジネス オブジェクト) を使用して、データとビジネス ロジックを保持します。 WPF は DataSet と同じくらい簡単にこれらのオブジェクトにバインドできますか?
ビジネス オブジェクトへのバインド
Windows フォームや ASP.NET を含む .NET の元の化身では、DataSet とその関連オブジェクトは一流の市民でした。 彼らは単純にデータをバインドし、うまく機能しました。 ただし、データを保持するためにオブジェクト モデルまたはビジネス オブジェクトを構築することを選択した場合は、オブジェクトのデータをコントロールに手動でバインドする必要がありました。 .NET 2.0 では、オブジェクトが一流の市民に発生し、オブジェクトへのバインドが簡略化されました。 WPF では、これは引き続き true です。 WPF では、 DataSet と同じくらい簡単にオブジェクトにバインドできます。
ビジネス オブジェクトを含むお気に入りの Employee Browser を作成するには、まず Employee を保持するクラスを作成しましょう。
C#
public class Employee
{
// Fields
int _employeeID;
string _firstName;
string _lastName;
string _title;
DateTime _hireDate;
BitmapImage _photo;
// Constructor
public Employee(IDataRecord record)
{
_employeeID = (int) record["EmployeeID"];
_firstName = (string) record["FirstName"];
_lastName = (string)record["LastName"];
_title = (string)record["Title"];
_hireDate = (DateTime)record["HireDate"];
CreatePhoto((byte[])record["Photo"]);
}
// BitmapImage creation
void CreatePhoto(byte[] photoSource)
{
// Create the bitmap object
// NOTE: This is *not* a GDI+ Bitmap object
_photo = new BitmapImage();
MemoryStream strm = new MemoryStream();
// Well-known hack to make Northwind images work
int offset = 78;
strm.Write(photoSource, offset, photoSource.Length - offset);
// Read the image into the bitmap object
_photo.BeginInit();
_photo.StreamSource = strm;
_photo.EndInit();
}
}
Visual Basic .NET
Public Class Employee
' Fields
Dim _employeeID As Integer
Dim _firstName As String
Dim _lastName As String
Dim _title As String
Dim _hireDate As DateTime
Dim _photo As BitmapImage
' Constructor
Public Sub New(ByVal record As IDataRecord)
_employeeID = CType(record("EmployeeID"), Integer)
_firstName = CType(record("FirstName"), String)
_lastName = CType(record("LastName"), String)
_title = CType(record("Title"), String)
_hireDate = CType(record("HireDate"), DateTime)
CreatePhoto(CType(record("Photo"), Byte()))
End Sub
' BitmapImage creation
Private Sub CreatePhoto(ByVal photoSource() As Byte)
' Create the bitmap object
' NOTE: This is *not* a GDI+ Bitmap object
_photo = New BitmapImage()
Dim strm As MemoryStream = New MemoryStream()
' Well-known hack to make Northwind images work
Dim offset As Integer = 78
strm.Write(photoSource, offset, photoSource.Length - offset)
' Read the image into the bitmap object
_photo.BeginInit()
_photo.StreamSource = strm
_photo.EndInit()
End Sub
End Class
このクラスは 、IDataRecord クラス ( DataReader の 1 つの結果を受け取りますが、1 分後に取得します) を受け取り、この記事で前述した DataTable の例で使用したのと同じフィールドに入力します。 ここでは BitmapImage の作成をビジネス オブジェクトに移動し、UI クラスで従業員を簡単に使用できるようにしました。
次に、フィールドのプロパティ アクセサーが必要です。
C#
// Read-Only
public int EmployeeID
{
get { return _employeeID; }
}
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
public string Title
{
get { return _title; }
set { _title = value; }
}
public DateTime HireDate
{
get { return _hireDate; }
set { _hireDate = value; }
}
// Read-Only
public BitmapImage Photo
{
get { return _photo; }
}
Visual Basic .NET
' Read-Only
Public ReadOnly Property EmployeeID() As Integer
Get
Return _employeeID
End Get
End Property
Public Property FirstName() As String
Get
Return _firstName
End Get
Set (ByVal Value As String)
_firstName = value
End Set
End Property
Public Property LastName() As String
Get
Return _lastName
End Get
Set (ByVal Value As String)
_lastName = value
End Set
End Property
Public Property Title() As String
Get
Return _title
End Get
Set (ByVal Value As String)
_title = value
End Set
End Property
Public Property HireDate() As DateTime
Get
Return _hireDate
End Get
Set (ByVal Value As DateTime)
_hireDate = value
End Set
End Property
' Read-Only
Public ReadOnly Property Photo() As BitmapImage
Get
Return _photo
End Get
End Property
ここでは、クラス内のフィールドへの読み取り/書き込み (または読み取り専用) アクセスを許可するだけです。
これで、従業員を保持するためのコレクションを作成できます。
C#
public class EmployeeList : ObservableCollection<Employee>
{
public EmployeeList()
{
string connString =
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
string query = @"
SELECT EmployeeID, FirstName, LastName, Title, HireDate, Photo
FROM Employees
";
// Fill the Set with the data
using (SqlConnection conn = new SqlConnection(connString))
{
try
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = query;
conn.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Add(new Employee(rdr));
}
}
finally
{
if (conn.State != ConnectionState.Closed) conn.Close();
}
}
}
}
Visual Basic .NET
Public Class EmployeeList
Inherits ObservableCollection<Employee>
Public Sub New()
String connString =
ConfigurationManager.ConnectionStrings("Northwind").ConnectionString
String query = _
"SELECT EmployeeID, FirstName, LastName, Title, HireDate, Photo " + _
" FROM Employees"
' Fill the Set with the data
Using conn as New SqlConnection(connString)
Try
Dim cmd As SqlCommand = conn.CreateCommand()
cmd.CommandText = query
conn.Open()
Dim rdr As SqlDataReader = cmd.ExecuteReader()
While rdr.Read()
Add(New Employee(rdr))
End While
Finally
If conn.State <> ConnectionState.Closed Then
conn.Close()
End If
End Try
End Using
End Sub
End Class
コレクションの基底クラスは ObservableCollection クラスです。これにより、UI が新しいメンバーがコレクションに追加されているかどうかを認識するためのメカニズムが提供されます。 UI ページからコレクション クラスにデータ アクセスを移動しました。 このクラスが作成されると、データベースに対してクエリを実行し、 DataReader から新しい従業員をコレクションに追加します。
コレクションと個々のオブジェクトが用意されたので、マッピングを使用してクラスを XAML にインポートできます ( この記事シリーズの最初の部分で詳しく説明します)。
<Window
...
xmlns:e="Example" DataContext="{StaticResource EmployeeList}"
>
<Window.Resources>
<e:EmployeeList x:Key="EmployeeList" />
...
</Window.Resources>
...
</Window>
クラスを XAML ドキュメントにインポートする場合は、 を使用します 。マッピング 宣言。 また、ウィンドウの DataContext として使用できるように、リソースに EmployeeList を指定します。 このようにして、XAML ファイルの残りの部分は元の Employee Browser と同じです。これは、 DataSet の例で使用したのと同じフィールド名に引き続き同じであるためです。 行うことができる唯一の変更は、分離コードで行うのではなく、XAML ドキュメント内の BitmapImage をバインドすることです。
...
<Image Name="theImage" Canvas.Top="5" Canvas.Left="5" Width="75"
Source="{Binding Path=Photo}"/>
...
これで、同じ動作をする Employee Browser が作成されました (図 3 を参照)。
図 3: ビジネス オブジェクトベースの従業員ブラウザー
型マッピングの使用に加えて、 ObjectDataProvider を使用してオブジェクトを XAML に取り込むこともできます。 この記事シリーズの最初の部分で示したように、必要なのはキーと型名を指定するだけです。
<ObjectDataProvider x:Key="EmployeeList"
TypeName="Example.Data.EmployeeList, ExampleCS"/>
x:Key はバインディングで使用されるモニカーに過ぎず、Typename はクラス名とアセンブリ (この場合は UI が存在するのと同じアセンブリ) です。 XAML の残りの部分は、同じデータに読み込んでいるため、同じままです。
ここはどこですか。
DataSets またはカスタム オブジェクトを使用してデータベースからデータを読み込み、データを WPF オブジェクトに直接バインドできるようになりました。 これで、最初の WPF データベース プロジェクトに進む準備ができました。
リファレンス
- WinFX SDK
- Chris Sells と Ian Griffith によるWindows Presentation Foundationのプログラミング
- この記事シリーズのパート 1