次の方法で共有


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、DataTablesDataRows など) とカスタム ビジネス オブジェクトという 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 でデータ バインディングを実行できます。 ComboBoxBinding は、親の DataContext からデータを取得するようにバインドに指示するだけです (この場合、ウィンドウDataContext が見つかるまでコントロール ツリーを上に移動します)。

    <ComboBox Name="theCombo" 
              IsSynchronizedWithCurrentItem="True"                                 ItemsSource="{Binding}" 
              ... />

IsSynchronizedWithCurrentItem 属性は、選択範囲が変更されたときに、ウィンドウに関する限り"現在のアイテム" が変更される点で重要です。 これにより、現在の項目を変更するためにこのオブジェクトが使用されることを WPF エンジンに指示します。 この属性がないと、 DataContext 内の現在の項目は変更されないため、テキスト ボックスはリストの最初の項目に残っていると見なします。

コンボ ボックスに従業員の名前を表示するには、DataTableFirstNameLastName を表示するバインドを 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"/>

画像の唯一の問題は、画像への写真データの自動バインドがサポートされていないことです。 これを容易にするために、ComboBoxSelectionChanged イベントを処理して画像を埋めることができます。

    <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 に示すようなインターフェイスが得られます。

Aa480226.wpfdabndpt201(en-us,MSDN.10).gif

図 1. 従業員ブラウザー

この簡単な例はかなり簡単ですが、DataSet 内で関連する 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

このコードでは、EmployeesOrders という 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 に示すように、選択したユーザーにのみ関連する注文情報のリスト ボックスが表示されます。

Aa480226.wpfdabndpt202(en-us,MSDN.10).gif

図 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 を参照)。

Aa480226.wpfdabndpt203(en-us,MSDN.10).gif

図 3: ビジネス オブジェクトベースの従業員ブラウザー

型マッピングの使用に加えて、 ObjectDataProvider を使用してオブジェクトを XAML に取り込むこともできます。 この記事シリーズの最初の部分で示したように、必要なのはキーと型名を指定するだけです。

    <ObjectDataProvider x:Key="EmployeeList" 
                        TypeName="Example.Data.EmployeeList, ExampleCS"/>

x:Key はバインディングで使用されるモニカーに過ぎず、Typename はクラス名とアセンブリ (この場合は UI が存在するのと同じアセンブリ) です。 XAML の残りの部分は、同じデータに読み込んでいるため、同じままです。

ここはどこですか。

DataSets またはカスタム オブジェクトを使用してデータベースからデータを読み込み、データを WPF オブジェクトに直接バインドできるようになりました。 これで、最初の WPF データベース プロジェクトに進む準備ができました。

リファレンス