チュートリアル: Visual Studio 2019 で最初の WPF アプリケーションを作成する
この記事では、ほとんどの WPF アプリケーションに共通する次の要素が含まれる Windows Presentation Foundation (WPF) デスクトップ アプリケーションを開発する方法について説明します: Extensible Application Markup Language (XAML) マークアップ、コードビハインド、アプリケーション定義、コントロール、レイアウト、データ バインディング、スタイル。 アプリケーションを開発するには、Visual Studio を使用します。
重要
この記事は .NET Framework 用に作成されました。 .NET 7 の概要については、「チュートリアル: 新しい WPF アプリを作成する (WPF .NET)」を参照してください。
このチュートリアルでは、次の作業を行う方法について説明します。
- WPF プロジェクトを作成する。
- XAML を使用して、アプリケーションのユーザー インターフェイス (UI) の外観をデザインする。
- アプリケーションの動作を構築するコードを記述する。
- アプリケーションを管理するためのアプリケーション定義を作成する。
- コントロールを追加し、レイアウトを作成して、アプリケーションの UI を構成する。
- アプリケーションの UI 全体に一貫性のある外観を持たせるためのスタイルを作成する。
- UI にデータを設定し、データと UI の同期を保つために、UI をデータにバインドする。
このチュートリアルの最後には、ユーザーが選択した個人の経費報告書を表示できる、スタンドアロンの Windows アプリケーションが完成します。 このアプリケーションは、ブラウザー スタイルのウィンドウでホストされる、複数の WPF ページから構成されます。
ヒント
このチュートリアルで使用するサンプル コードには Visual Basic 版と C# 版があり、WPF アプリ チュートリアルのサンプル コードで入手できます。
このページの先頭にある言語セレクターを使用して、サンプル コードのコード言語を C# と Visual Basic の間で切り替えることができます。
必須コンポーネント
.NET デスクトップ開発ワークロードがインストールされた Visual Studio 2019。
Visual Studio の最新バージョンのインストールの詳細については、「Visual Studio のインストール」を参照してください。
アプリケーション プロジェクトを作成する
最初のステップでは、アプリケーション定義、2 つのページ、および 1 つの画像が含まれる、アプリケーション インフラストラクチャを作成します。
ExpenseIt
という名前の新しい WPF アプリケーション プロジェクトを Visual Basic または Visual C# で作成します。Visual Studio を開き、 [作業の開始] メニューの [新しいプロジェクトの作成] を選択します。
[新しいプロジェクトの作成] ダイアログが開きます。
[言語] ドロップダウンで、 [C#] または [Visual Basic] を選択します。
[WPF アプリ (.NET Framework)] テンプレートを選択し、 [次へ] を選択します。
[新しいプロジェクトを構成します] ダイアログが開きます。
プロジェクトの名前に「
ExpenseIt
」と入力して、 [OK] を選択します。Visual Studio によってプロジェクトが作成され、デザイナーで MainWindow.xaml という名前の既定のアプリケーション ウィンドウが開きます。
Application.xaml (Visual Basic) または App.xaml (C#) を開きます。
この XAML ファイルでは、WPF アプリケーションとすべてのアプリケーション リソースを定義します。 また、このファイルを使用して、アプリケーションの起動時に自動的に表示される UI (この例では MainWindow.xaml) も指定します。
XAML は、Visual Basic では次のようになります。
<Application x:Class="Application" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml"> <Application.Resources> </Application.Resources> </Application>
C# では次のようになります。
<Application x:Class="ExpenseIt.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml"> <Application.Resources> </Application.Resources> </Application>
MainWindow.xaml を開きます。
この XAML ファイルは、アプリケーションのメイン ウィンドウです。このファイルには、ページで作成されたコンテンツが表示されます。 Window クラスでは、ウィンドウのプロパティ (タイトル、サイズ、アイコンなど) が定義されており、イベント (ウィンドウを閉じたり非表示にしたりするなど) が処理されます。
次の XAML で示されているように、Window 要素を NavigationWindow に変更します。
<NavigationWindow x:Class="ExpenseIt.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ... </NavigationWindow>
このアプリでは、ユーザーの入力に応じて画面がさまざまなコンテンツに移動します。 このため、メインの Window を NavigationWindow に変更する必要があります。 NavigationWindow では、Window のすべてのプロパティを継承します。 XAML ファイル内の NavigationWindow 要素では、NavigationWindow クラスのインスタンスが作成されます。 詳しくは、「ナビゲーションの概要」をご覧ください。
NavigationWindow タグの間から Grid 要素を削除します。
XAML コードで、NavigationWindow 要素に対する次のプロパティを変更します。
XAML は、Visual Basic では次のようになります。
<NavigationWindow x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ExpenseIt" Height="350" Width="500"> </NavigationWindow>
C# では次のようになります。
<NavigationWindow x:Class="ExpenseIt.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ExpenseIt" Height="350" Width="500"> </NavigationWindow>
MainWindow.xaml.vb または MainWindow.xaml.cs を開きます。
このファイルは、MainWindow.xaml で宣言されたイベントを処理するコードが含まれる分離コード ファイルです。 このファイルには、XAML で定義されたウィンドウの部分クラスが含まれています。
C# を使用している場合は、NavigationWindow から派生するように
MainWindow
クラスを変更します。 (Visual Basic では、XAML でウィンドウを変更すると自動的にこの処理が行われます)。これで、C# のコードは次のようになっているはずです。using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace ExpenseIt { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : NavigationWindow { public MainWindow() { InitializeComponent(); } } }
ファイルをアプリケーションに追加する
このセクションでは、アプリケーションに 2 つのページと 1 つのイメージを追加します。
新しいページをプロジェクトに追加し、名前を
ExpenseItHome.xaml
に設定します。ソリューション エクスプローラーで、
ExpenseIt
プロジェクト ノードを右クリックして、 [追加]>[ページ] を選択します。[新しい項目の追加] ダイアログでは、 [ページ (WPF)] テンプレートが既に選択されています。 名前に「
ExpenseItHome
」と入力し、 [追加] を選択します。
このページが、アプリケーションの起動時に表示される最初のページになります。 経費報告書の表示対象として選択するユーザーの一覧が表示されます。
ExpenseItHome.xaml
を開きます。Title を "
ExpenseIt - Home
" に設定します。DesignHeight
を 350 ピクセルに設定し、DesignWidth
を 500 ピクセルに設定します。XAML は、Visual Basic では次のようになります。
<Page x:Class="ExpenseItHome" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="350" d:DesignWidth="500" Title="ExpenseIt - Home"> <Grid> </Grid> </Page>
C# では次のようになります。
<Page x:Class="ExpenseIt.ExpenseItHome" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="350" d:DesignWidth="500" Title="ExpenseIt - Home"> <Grid> </Grid> </Page>
MainWindow.xaml を開きます。
Source プロパティを NavigationWindow 要素に追加し、それを "
ExpenseItHome.xaml
" に設定します。これにより、
ExpenseItHome.xaml
が、アプリケーションの起動時に最初に開くページとして設定されます。Visual Basic での XAML の例:
<NavigationWindow x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ExpenseIt" Height="350" Width="500" Source="ExpenseItHome.xaml"> </NavigationWindow>
C# の場合:
<NavigationWindow x:Class="ExpenseIt.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ExpenseIt" Height="350" Width="500" Source="ExpenseItHome.xaml"> </NavigationWindow>
ヒント
また、 [プロパティ] ウィンドウの [Miscellaneous] カテゴリで、 [Source] プロパティを設定することもできます。
別の新しい WPF ページをプロジェクトに追加し、ExpenseReportPage.xaml という名前にします。
ソリューション エクスプローラーで、
ExpenseIt
プロジェクト ノードを右クリックして、 [追加]>[ページ] を選択します。[新しい項目の追加] ダイアログで、 [ページ (WPF)] テンプレートを選択します。 名前に「ExpenseReportPage」と入力し、 [追加] を選択します。
このページには、
ExpenseItHome
ページで選択されたユーザーの経費報告書が表示されます。ExpenseReportPage.xamlを開きます。
Title を "
ExpenseIt - View Expense
" に設定します。DesignHeight
を 350 ピクセルに設定し、DesignWidth
を 500 ピクセルに設定します。ExpenseReportPage.xaml は、Visual Basic では次のようになります。
<Page x:Class="ExpenseReportPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="350" d:DesignWidth="500" Title="ExpenseIt - View Expense"> <Grid> </Grid> </Page>
C# では次のようになります。
<Page x:Class="ExpenseIt.ExpenseReportPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="350" d:DesignWidth="500" Title="ExpenseIt - View Expense"> <Grid> </Grid> </Page>
ExpenseItHome.xaml.vb と ExpenseReportPage.xaml.vb を開くか、または ExpenseItHome.xaml.cs と ExpenseReportPage.xaml.cs を開きます。
新しいページ ファイルを作成すると、Visual Studio によってその "分離コード" ファイルが自動的に作成されます。 これらの分離コード ファイルでは、ユーザー入力に対応するためのロジックを処理します。
ExpenseItHome
のコードは次のようになります。using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace ExpenseIt { /// <summary> /// Interaction logic for ExpenseItHome.xaml /// </summary> public partial class ExpenseItHome : Page { public ExpenseItHome() { InitializeComponent(); } } }
Class ExpenseItHome End Class
ExpenseReportPage は次のようになります。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace ExpenseIt { /// <summary> /// Interaction logic for ExpenseReportPage.xaml /// </summary> public partial class ExpenseReportPage : Page { public ExpenseReportPage() { InitializeComponent(); } } }
Class ExpenseReportPage End Class
watermark.png という名前の画像をプロジェクトに追加します。 独自の画像を作成したり、サンプル コードからファイルをコピーしたり、microsoft/WPF-Samples GitHub リポジトリから取得したりすることができます。
プロジェクト ノードを右クリックし、 [追加]>[既存の項目] を選択するか、Shift+Alt+A キーを押します。
[Add Existing Item](既存項目の追加) ダイアログで、ファイル フィルターを [すべてのファイル] または [画像ファイル] に設定し、使用する画像ファイルを参照して、 [追加] を選択します。
ソリューション エクスプローラーでイメージ ファイルを選択し、[プロパティ] ウィンドウで [ビルド アクション] を [リソース] に設定します。
アプリケーションのビルドと実行
アプリケーションをビルドして実行するには、F5 キーを押すか、 [デバッグ] メニューの [デバッグの開始] を選択します。
NavigationWindow ボタンが含まれるアプリケーションは、次の図のようになります。
アプリケーションを閉じて Visual Studio に戻ります。
レイアウトを作成する
レイアウトを使用すると、順序付けされた方法で UI 要素を配置できます。また、UI のサイズが変更された場合の要素のサイズと位置が管理されます。 通常、レイアウトを作成するには、次のいずれかのレイアウト コントロールを使用します。
- Canvas - キャンバス領域に対する相対座標を使用して子要素を明示的に配置する領域を定義します。
- DockPanel - 子要素を互いに水平方向または垂直方向に整列する領域を定義します。
- Grid - 行と列で構成される柔軟性のあるグリッド領域を定義します。
- StackPanel - 子要素を水平方向または垂直方向の単一行に整列します。
- VirtualizingStackPanel - 水平方向または垂直方向の単一行でコンテンツを整列し、仮想化します。
- WrapPanel - 左から右へ順に子要素を配置し、ボックスの端で改行してコンテンツを次の行へ送ります。 後続の配置は、Orientation プロパティの値に応じて、上から下または右から左に向かって行われます。
これらの各レイアウト コントロールでは、その子要素に対する特定の種類のレイアウトがサポートされています。 ExpenseIt
のページはサイズの変更が可能で、各ページの要素は縦にも横にも他の要素と揃えられます。 この例では、アプリケーションのレイアウト要素として Grid を使用します。
このセクションでは、 ExpenseItHome.xaml
の Grid に列と行の定義を追加して、10 ピクセルのマージンを持つ 3 行 1 列のテーブルを作成します。
ExpenseItHome.xaml
で、Grid 要素の Margin プロパティを "10,0,10,10" に設定します。これは、左、上、右、下の余白に対応しています。<Grid Margin="10,0,10,10">
ヒント
また、 [プロパティ] ウィンドウの [レイアウト] カテゴリで、Margin の値を設定することもできます。
Grid タグの間に次の XAML を追加して、行と列の定義を作成します。
<Grid.ColumnDefinitions> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition /> <RowDefinition Height="Auto"/> </Grid.RowDefinitions>
2 行の Height は Auto に設定されます。つまり、行のサイズは、行の内容に基づいて設定されます。 既定の Height は Star のサイズ設定です。これは、行の高さが使用可能な領域の加重比率であることを意味します。 たとえば、2 つの行それぞれの Height が "*" の場合、各行の高さは、使用可能なスペースの半分になります。
Grid は次の XAML のようになっているはずです。
<Grid Margin="10,0,10,10"> <Grid.ColumnDefinitions> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition /> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> </Grid>
コントロールを追加する
このセクションでは、ホームページの UI を更新して、ユーザーの一覧が表示されるようにします。ここで、経費報告書を表示するユーザーを 1 人選択します。 コントロールとは、ユーザーがアプリケーションと対話できるようにする UI オブジェクトのことです。 詳しくは、「 コントロール」をご覧ください。
この UI を作成するには、次の要素を ExpenseItHome.xaml
に追加します。
各コントロールは、Grid.Row 添付プロパティを設定することで、Grid の行に配置されます。 添付プロパティについて詳しくは、「添付プロパティの概要」をご覧ください。
ExpenseItHome.xaml
で、Grid タグの間のどこかに次の XAML を追加します。<!-- People list --> <Border Grid.Column="0" Grid.Row="0" Height="35" Padding="5" Background="#4E87D4"> <Label VerticalAlignment="Center" Foreground="White">Names</Label> </Border> <ListBox Name="peopleListBox" Grid.Column="0" Grid.Row="1"> <ListBoxItem>Mike</ListBoxItem> <ListBoxItem>Lisa</ListBoxItem> <ListBoxItem>John</ListBoxItem> <ListBoxItem>Mary</ListBoxItem> </ListBox> <!-- View report button --> <Button Grid.Column="0" Grid.Row="2" Margin="0,10,0,10" Width="125" Height="25" HorizontalAlignment="Right">View</Button>
ヒント
コントロールを [ツールボックス] ウィンドウからデザイン ウィンドウにドラッグし、 [プロパティ] ウィンドウでプロパティを設定することよって、コントロールを作成することもできます。
アプリケーションをビルドして実行します。
次の図では、作成したコントロールを示します。
画像とタイトルを追加する
このセクションでは、画像とページ タイトルでホーム ページの UI を更新します。
ExpenseItHome.xaml
で、ColumnDefinitions に、Width が 230 ピクセルで固定された新しい列を追加します。<Grid.ColumnDefinitions> <ColumnDefinition Width="230" /> <ColumnDefinition /> </Grid.ColumnDefinitions>
RowDefinitions に別の行を追加します。全部で 4 行になります。
<Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="Auto"/> <RowDefinition /> <RowDefinition Height="Auto"/> </Grid.RowDefinitions>
3 つの各コントロール (Border、ListBox、Button) で、Grid.Column プロパティを 1 に設定して、コントロールを 2 列目に移動します。
3 つの各コントロール (Border、ListBox、Button) と Border 要素の Grid.Row の値を 1 だけインクリメントして、各コントロールを 1 行下に移動します。
3 つのコントロールの XAML は、次のようになります。
<Border Grid.Column="1" Grid.Row="1" Height="35" Padding="5" Background="#4E87D4"> <Label VerticalAlignment="Center" Foreground="White">Names</Label> </Border> <ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2"> <ListBoxItem>Mike</ListBoxItem> <ListBoxItem>Lisa</ListBoxItem> <ListBoxItem>John</ListBoxItem> <ListBoxItem>Mary</ListBoxItem> </ListBox> <!-- View report button --> <Button Grid.Column="1" Grid.Row="3" Margin="0,10,0,0" Width="125" Height="25" HorizontalAlignment="Right">View</Button>
<Grid>
タグと</Grid>
タグの間のどこかに次の XAML を追加して、Background プロパティを watermark.png 画像ファイルに設定します。<Grid.Background> <ImageBrush ImageSource="watermark.png"/> </Grid.Background>
Border 要素の前に、"View Expense Report" という内容の Label を追加します。 このラベルはページのタイトルです。
<Label Grid.Column="1" VerticalAlignment="Center" FontFamily="Trebuchet MS" FontWeight="Bold" FontSize="18" Foreground="#0066cc"> View Expense Report </Label>
アプリケーションをビルドして実行します。
次の図では、追加した結果を示します。
イベントを処理するコードを追加する
ExpenseItHome.xaml
で、Button 要素に Click イベント ハンドラーを追加します。 詳細については、「方法:単純なイベント ハンドラーを作成する」を参照してください。<!-- View report button --> <Button Grid.Column="1" Grid.Row="3" Margin="0,10,0,0" Width="125" Height="25" HorizontalAlignment="Right" Click="Button_Click">View</Button>
ExpenseItHome.xaml.vb
またはExpenseItHome.xaml.cs
を開きます。次のコードを
ExpenseItHome
クラスに追加して、ボタン クリック イベント ハンドラーを追加します。 イベント ハンドラーによって、ExpenseReportPage ページが開かれます。private void Button_Click(object sender, RoutedEventArgs e) { // View Expense Report ExpenseReportPage expenseReportPage = new ExpenseReportPage(); this.NavigationService.Navigate(expenseReportPage); }
Private Sub Button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) ' View Expense Report Dim expenseReportPage As New ExpenseReportPage() Me.NavigationService.Navigate(expenseReportPage) End Sub
ExpenseReportPage の UI を作成する
ExpenseReportPage.xaml には、 ExpenseItHome
ページで選択された個人の経費報告書が表示されます。 このセクションでは、ExpenseReportPage ページの UI を作成します。 また、さまざまな UI 要素に背景と塗りつぶしの色も追加します。
ExpenseReportPage.xamlを開きます。
Grid タグの間に次の XAML を追加します。
<Grid.Background> <ImageBrush ImageSource="watermark.png" /> </Grid.Background> <Grid.ColumnDefinitions> <ColumnDefinition Width="230" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <Label Grid.Column="1" VerticalAlignment="Center" FontFamily="Trebuchet MS" FontWeight="Bold" FontSize="18" Foreground="#0066cc"> Expense Report For: </Label> <Grid Margin="10" Grid.Column="1" Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <!-- Name --> <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal"> <Label Margin="0,0,0,5" FontWeight="Bold">Name:</Label> <Label Margin="0,0,0,5" FontWeight="Bold"></Label> </StackPanel> <!-- Department --> <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Orientation="Horizontal"> <Label Margin="0,0,0,5" FontWeight="Bold">Department:</Label> <Label Margin="0,0,0,5" FontWeight="Bold"></Label> </StackPanel> <Grid Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" VerticalAlignment="Top" HorizontalAlignment="Left"> <!-- Expense type and Amount table --> <DataGrid AutoGenerateColumns="False" RowHeaderWidth="0" > <DataGrid.ColumnHeaderStyle> <Style TargetType="{x:Type DataGridColumnHeader}"> <Setter Property="Height" Value="35" /> <Setter Property="Padding" Value="5" /> <Setter Property="Background" Value="#4E87D4" /> <Setter Property="Foreground" Value="White" /> </Style> </DataGrid.ColumnHeaderStyle> <DataGrid.Columns> <DataGridTextColumn Header="ExpenseType" /> <DataGridTextColumn Header="Amount" /> </DataGrid.Columns> </DataGrid> </Grid> </Grid>
この UI は、DataGrid にレポート データが表示される点を除き、
ExpenseItHome.xaml
と似ています。アプリケーションをビルドして実行します。
[View] ボタンを選択します。
経費明細書ページが表示されます。 戻るナビゲーション ボタンが有効になっていることにも注意してください。
ExpenseReportPage.xaml に追加された UI 要素を次の図に示します。
スタイル コントロール
多くの場合、UI では、要素の種類が同じであれば、外観もすべて同じになります。 UI では、複数の要素間で外観を再利用できるように、スタイルが使用されます。 スタイルの再利用性により、XAML の作成と管理が簡略化されます。 このセクションでは、これまでの手順で定義した要素ごとの属性を、スタイルに置き換えます。
Application.xaml または App.xaml を開きます。
Application.Resources タグの間に次の XAML を追加します。
<!-- Header text style --> <Style x:Key="headerTextStyle"> <Setter Property="Label.VerticalAlignment" Value="Center"></Setter> <Setter Property="Label.FontFamily" Value="Trebuchet MS"></Setter> <Setter Property="Label.FontWeight" Value="Bold"></Setter> <Setter Property="Label.FontSize" Value="18"></Setter> <Setter Property="Label.Foreground" Value="#0066cc"></Setter> </Style> <!-- Label style --> <Style x:Key="labelStyle" TargetType="{x:Type Label}"> <Setter Property="VerticalAlignment" Value="Top" /> <Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="FontWeight" Value="Bold" /> <Setter Property="Margin" Value="0,0,0,5" /> </Style> <!-- DataGrid header style --> <Style x:Key="columnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}"> <Setter Property="Height" Value="35" /> <Setter Property="Padding" Value="5" /> <Setter Property="Background" Value="#4E87D4" /> <Setter Property="Foreground" Value="White" /> </Style> <!-- List header style --> <Style x:Key="listHeaderStyle" TargetType="{x:Type Border}"> <Setter Property="Height" Value="35" /> <Setter Property="Padding" Value="5" /> <Setter Property="Background" Value="#4E87D4" /> </Style> <!-- List header text style --> <Style x:Key="listHeaderTextStyle" TargetType="{x:Type Label}"> <Setter Property="Foreground" Value="White" /> <Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="HorizontalAlignment" Value="Left" /> </Style> <!-- Button style --> <Style x:Key="buttonStyle" TargetType="{x:Type Button}"> <Setter Property="Width" Value="125" /> <Setter Property="Height" Value="25" /> <Setter Property="Margin" Value="0,10,0,0" /> <Setter Property="HorizontalAlignment" Value="Right" /> </Style>
この XAML は、次のスタイルを追加します。
headerTextStyle
:ページ タイトルの Label の書式を設定します。labelStyle
:Label コントロールの書式を設定します。columnHeaderStyle
:DataGridColumnHeader の書式を設定します。listHeaderStyle
:リスト ヘッダーの Border コントロールの書式を設定します。listHeaderTextStyle
:リスト ヘッダーの Label の書式を設定します。buttonStyle
:ExpenseItHome.xaml
で Button の書式を設定します。
スタイルはリソースであり、Application.Resources プロパティ要素の子であることに注意してください。 ここでは、スタイルはアプリケーション内のすべての要素に適用されます。 .NET アプリでリソースを使用する例については、アプリケーション リソースの使用に関する記事を参照してください。
ExpenseItHome.xaml
で、Grid 要素の間のすべてを次の XAML に置き換えます。<Grid.Background> <ImageBrush ImageSource="watermark.png" /> </Grid.Background> <Grid.ColumnDefinitions> <ColumnDefinition Width="230" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="Auto"/> <RowDefinition /> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <!-- People list --> <Label Grid.Column="1" Style="{StaticResource headerTextStyle}" > View Expense Report </Label> <Border Grid.Column="1" Grid.Row="1" Style="{StaticResource listHeaderStyle}"> <Label Style="{StaticResource listHeaderTextStyle}">Names</Label> </Border> <ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2"> <ListBoxItem>Mike</ListBoxItem> <ListBoxItem>Lisa</ListBoxItem> <ListBoxItem>John</ListBoxItem> <ListBoxItem>Mary</ListBoxItem> </ListBox> <!-- View report button --> <Button Grid.Column="1" Grid.Row="3" Click="Button_Click" Style="{StaticResource buttonStyle}">View</Button>
各コントロールの外観を定義する VerticalAlignment や FontFamily などのプロパティは、これらのスタイルを適用することで、削除されて置き換えられます。 たとえば、"View Expense Report" という Label には、
headerTextStyle
が適用されます。ExpenseReportPage.xamlを開きます。
Grid 要素の間のすべてを、次の XAML に置き換えます。
<Grid.Background> <ImageBrush ImageSource="watermark.png" /> </Grid.Background> <Grid.ColumnDefinitions> <ColumnDefinition Width="230" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <Label Grid.Column="1" Style="{StaticResource headerTextStyle}"> Expense Report For: </Label> <Grid Margin="10" Grid.Column="1" Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <!-- Name --> <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal"> <Label Style="{StaticResource labelStyle}">Name:</Label> <Label Style="{StaticResource labelStyle}"></Label> </StackPanel> <!-- Department --> <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Orientation="Horizontal"> <Label Style="{StaticResource labelStyle}">Department:</Label> <Label Style="{StaticResource labelStyle}"></Label> </StackPanel> <Grid Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" VerticalAlignment="Top" HorizontalAlignment="Left"> <!-- Expense type and Amount table --> <DataGrid ColumnHeaderStyle="{StaticResource columnHeaderStyle}" AutoGenerateColumns="False" RowHeaderWidth="0" > <DataGrid.Columns> <DataGridTextColumn Header="ExpenseType" /> <DataGridTextColumn Header="Amount" /> </DataGrid.Columns> </DataGrid> </Grid> </Grid>
アプリケーションをビルドして実行します。 ウィンドウの外観は、以前と同じです。
アプリケーションを閉じて Visual Studio に戻ります。
データをコントロールにバインドする
このセクションでは、さまざまなコントロールにバインドされる XML データを作成します。
ExpenseItHome.xaml
で、開始 Grid 要素の後に次の XAML を追加して、各個人のデータを含む XmlDataProvider を作成します。<Grid.Resources> <!-- Expense Report Data --> <XmlDataProvider x:Key="ExpenseDataSource" XPath="Expenses"> <x:XData> <Expenses xmlns=""> <Person Name="Mike" Department="Legal"> <Expense ExpenseType="Lunch" ExpenseAmount="50" /> <Expense ExpenseType="Transportation" ExpenseAmount="50" /> </Person> <Person Name="Lisa" Department="Marketing"> <Expense ExpenseType="Document printing" ExpenseAmount="50"/> <Expense ExpenseType="Gift" ExpenseAmount="125" /> </Person> <Person Name="John" Department="Engineering"> <Expense ExpenseType="Magazine subscription" ExpenseAmount="50"/> <Expense ExpenseType="New machine" ExpenseAmount="600" /> <Expense ExpenseType="Software" ExpenseAmount="500" /> </Person> <Person Name="Mary" Department="Finance"> <Expense ExpenseType="Dinner" ExpenseAmount="100" /> </Person> </Expenses> </x:XData> </XmlDataProvider> </Grid.Resources>
データは Grid リソースとして作成されます。 通常、このデータはファイルとして読み込まれますが、説明を簡単にするため、データをインラインで追加します。
<Grid.Resources>
要素内の<XmlDataProvider>
要素の後に、ListBox でのデータの表示方法を定義する次の<xref:System.Windows.DataTemplate>
要素を追加します。<Grid.Resources> <!-- Name item template --> <DataTemplate x:Key="nameItemTemplate"> <Label Content="{Binding XPath=@Name}"/> </DataTemplate> </Grid.Resources>
データ テンプレートについて詳しくは、「データ テンプレートの概要」をご覧ください。
既存の ListBox を次の XAML に置き換えます。
<ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2" ItemsSource="{Binding Source={StaticResource ExpenseDataSource}, XPath=Person}" ItemTemplate="{StaticResource nameItemTemplate}"> </ListBox>
この XAML では、ListBox の ItemsSource プロパティがデータ ソースにバインドされ、データ テンプレートが ItemTemplate として適用されます。
コントロールにデータを接続する
次に、 ExpenseItHome
ページで選択された名前を取得し、それを ExpenseReportPage のコンストラクターに渡すコードを追加します。 ExpenseReportPage では、渡された項目を使用してデータ コンテキストが設定されます。それが、ExpenseReportPage.xaml で定義されているコントロールのバインド先になります。
ExpenseReportPage.xaml.vb または ExpenseReportPage.xaml.csを開きます。
オブジェクトを取得するコンストラクターを追加して、選択した個人の経費報告書データを渡せるようにします。
public partial class ExpenseReportPage : Page { public ExpenseReportPage() { InitializeComponent(); } // Custom constructor to pass expense report data public ExpenseReportPage(object data):this() { // Bind to expense report data. this.DataContext = data; } }
Partial Public Class ExpenseReportPage Inherits Page Public Sub New() InitializeComponent() End Sub ' Custom constructor to pass expense report data Public Sub New(ByVal data As Object) Me.New() ' Bind to expense report data. Me.DataContext = data End Sub End Class
ExpenseItHome.xaml.vb
またはExpenseItHome.xaml.cs
を開きます。選択された個人の経費報告書データを渡す新しいコンストラクターを呼び出すように、Click イベント ハンドラーを変更します。
private void Button_Click(object sender, RoutedEventArgs e) { // View Expense Report ExpenseReportPage expenseReportPage = new ExpenseReportPage(this.peopleListBox.SelectedItem); this.NavigationService.Navigate(expenseReportPage); }
Private Sub Button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) ' View Expense Report Dim expenseReportPage As New ExpenseReportPage(Me.peopleListBox.SelectedItem) Me.NavigationService.Navigate(expenseReportPage) End Sub
データ テンプレートを使用したデータのスタイル設定
このセクションでは、データ テンプレートを使用して、データ バインド リスト内の各項目の UI を更新します。
ExpenseReportPage.xamlを開きます。
"Name" および "Department" の Label 要素の内容を、適切なデータ ソース プロパティにバインドします。 データ バインディングの詳細については、「データ バインディングの概要」を参照してください。
<!-- Name --> <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal"> <Label Style="{StaticResource labelStyle}">Name:</Label> <Label Style="{StaticResource labelStyle}" Content="{Binding XPath=@Name}"></Label> </StackPanel> <!-- Department --> <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Orientation="Horizontal"> <Label Style="{StaticResource labelStyle}">Department:</Label> <Label Style="{StaticResource labelStyle}" Content="{Binding XPath=@Department}"></Label> </StackPanel>
開始の Grid 要素の後に、経費報告書データの表示方法を定義する、次のデータ テンプレートを追加します。
<!--Templates to display expense report data--> <Grid.Resources> <!-- Reason item template --> <DataTemplate x:Key="typeItemTemplate"> <Label Content="{Binding XPath=@ExpenseType}"/> </DataTemplate> <!-- Amount item template --> <DataTemplate x:Key="amountItemTemplate"> <Label Content="{Binding XPath=@ExpenseAmount}"/> </DataTemplate> </Grid.Resources>
DataGrid 要素の下の DataGridTextColumn 要素を DataGridTemplateColumn に置き換えて、それらにテンプレートを適用します。 また、
DataGrid
要素に値を指定してItemsSource
属性も指定します。<!-- Expense type and Amount table --> <DataGrid ItemsSource="{Binding XPath=Expense}" ColumnHeaderStyle="{StaticResource columnHeaderStyle}" AutoGenerateColumns="False" RowHeaderWidth="0" > <DataGrid.Columns> <DataGridTemplateColumn Header="ExpenseType" CellTemplate="{StaticResource typeItemTemplate}" /> <DataGridTemplateColumn Header="Amount" CellTemplate="{StaticResource amountItemTemplate}" /> </DataGrid.Columns> </DataGrid>
アプリケーションをビルドして実行します。
個人を選択し、 [View] ボタンを選択します。
次の図には、コントロール、レイアウト、スタイル、データ バインディング、データ テンプレートが適用された ExpenseIt
アプリケーションの両方のページが示されています。
Note
このサンプルは、WPF の特定の機能について説明するものであり、セキュリティ、ローカライズ、アクセシビリティなどのベスト プラクティスには従っていません。 WPF と .NET アプリの開発に関する包括的なベスト プラクティスについては、次のトピックをご覧ください。
次の手順
このチュートリアルでは、Windows Presentation Foundation (WPF) を使用して UI を作成するためのいくつかの手法について学習しました。 データ バインドされた .NET アプリの構成要素についての基本を理解することもできました。 WPF のアーキテクチャおよびプログラミング モデルの詳細については、次のトピックを参照してください。
アプリケーションの作成の詳細については、次のトピックを参照してください。
関連項目
.NET Desktop feedback