WPF

【C#/WPF実践入門編(4)】WPFの主要コントロール入門 ~ListView、ComboBox、TabControl、Image等の使い方~

Windows Presentation Foundation (WPF) の主要なコントロールについて、実際にアプリを作りながら学びます。

今回は、WPFでよく使われる基本的なコントロールの使い方と特徴を学びます。以下の方に役立つ内容となっています。

  • WPFのコントロールにどのようなものがあるかを体系的に知りたい方
  • WPFで実践的なUI作成を学びたい方

コントロールにどのようなものがあるか体系的に俯瞰した上で、代表的なものをピックアップして具体的に説明します。

演習では、コントロールを組み合わせて以下のようなリスト型メモ帳アプリを作成します。

プロ太

コントロールはTextBox、Buttonなど、これまでにもでてきましたね。

前回学んだGrid、StackPanelなどのパネルもコントロールの一種です。

今回、あらためてWPFにどのようなコントロールがあるのかを一緒に学んでいきましょう!

演習のコード一式はGitHubに置いてあります。

YouTube動画は以下です。

講義:WPFのコントロール

コントロールの役割

WPFでは、コントロールを使用してユーザインターフェース(UI)を構築します。

プロ太

コントロールはユーザとアプリの接点となる重要な要素です。

ボタンを押す、テキストを入力する、リストから選択するなど、すべてコントロールを通じて行われます。

コントロールは以下の役割を担います。

  • 表示: データや情報をユーザに見やすく表示
  • 入力: ユーザからの入力やデータ編集を受け付け
  • 操作: クリックや選択などのユーザ操作に応答
  • フィードバック: アプリの状態や処理結果をユーザに通知

コントロールの分類と代表例

WPFには多くのコントロールがありますが、機能別に以下のように分類できます。
(Microsoft LearnのWPFカテゴリ別コントロールにおける分類です。)

カテゴリ役割代表的なコントロール
レイアウトボタンやテキストなどの部品を画面上に並べるGrid、StackPanel、DockPanel、Canvas、Border、Panel、WrapPanel
ボタンユーザがクリックして何かの処理を実行するButton、RepeatButton
選択複数の選択肢からユーザが好みのものを選ぶCheckBox、ComboBox、ListBox、RadioButton、Slider
入力ユーザがキーボードで文字や数値を入力するTextBox、RichTextBox、PasswordBox
データ表示大量のデータを表やリスト形式で見せるDataGrid、ListView、TreeView
日付の表示と選択カレンダーを表示してユーザが日付を選ぶCalendar、DatePicker
メニュー機能をまとめて整理し、ユーザが選択可能にするContextMenu、Menu、ToolBar
ナビゲーション画面を切り替えたりページ間を移動するFrame、Hyperlink、Page、NavigationWindow、TabControl
ダイアログボックスファイルを開く・保存するなどの操作画面を表示OpenFileDialog、PrintDialog、SaveFileDialog
ユーザ情報説明文や進行状況をユーザに分かりやすく表示AccessText、Label、Popup、ProgressBar、StatusBar、TextBlock、ToolTip
ドキュメント文書ファイルを画面に表示して読みやすくするDocumentViewer、FlowDocumentPageViewer、FlowDocumentReader、FlowDocumentScrollViewer、StickyNoteControl
メディア画像・音楽・動画などのファイルを再生・表示Image、MediaElement、SoundPlayerAction
デジタルインクタブレットペンで手書き文字や絵を描くInkCanvas、InkPresenter
プロ美

すごいたくさんある…!

プロ太

全部覚える必要はありません。ざっくり、このようなカテゴリがあるという雰囲気を掴んでもらえればOKです。

演習では、これまでで登場してきたGrid(レイアウト系)、Button(ボタン系)、TextBox(入力系)、Label(ユーザ情報系)などの他に、新たに以下のコントロールも使います。

  • ListView(データ表示系
  • ComboBox(選択系
  • TabControl(ナビゲーション系
  • Image(メディア系

これらについてそれぞれ簡単に紹介します。

コントロール紹介

ListView

ListViewはデータを一覧形式で表示するコントロールです。

以下が例です。

<ListView x:Name="ItemListView">
    <ListViewItem Content="項目1"/>
    <ListViewItem Content="項目2"/>
</ListView>

ListViewは、以下の例のようにクラスオブジェクトを表示することもできます。

<ListView x:Name="MyListView">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="名前" DisplayMemberBinding="{Binding Name}"/>
            <GridViewColumn Header="年齢" DisplayMemberBinding="{Binding Age}"/>
        </GridView>
    </ListView.View>
</ListView>

C#コードビハインドでListViewに表示するデータを設定します。

...
 public partial class MainWindow : Window
 {
     public MainWindow()
     {
         InitializeComponent();

         // データを作成
         var people = new List<Person>
             {
                 new Person { Name = "田中", Age = 30 },
                 new Person { Name = "佐藤", Age = 25 }
             };

         // ListViewにデータを設定
         MyListView.ItemsSource = people;
     }
 }

 public class Person
 {
     public string Name { get; set; }
     public int Age { get; set; }
 }
...
プロ太

このようにデータ(peopleリスト)とUI(ListView)を直接紐づける方法を「データバインディング」と呼びます。

WPFの特徴的な仕組みの一つで、次回の記事で詳しく解説する予定です。

ComboBox

ComboBoxはドロップダウンリストから選択肢を選ぶコントロールです。

以下が例です。

<ComboBox x:Name="CategoryComboBox">
    <ComboBoxItem Content="仕事"/>
    <ComboBoxItem Content="個人" IsSelected="True"/>
</ComboBox>
プロ太

この例では、選択肢(ComboBoxItem)を直接書いています。

ComboBoxもListViewと同様に、ItemsSourceを使ってデータと紐づけて表示することができます。
(たとえば、カテゴリリストをコード側で用意してバインドする、など)

TabControl

TabControlはタブ形式で複数の画面を切り替えるコントロールです。

以下が例です。

<TabControl>
    <TabItem Header="メモ">
        <!-- メモ入力画面 -->
    </TabItem>
    <TabItem Header="設定">
        <!-- 設定画面 -->
    </TabItem>
</TabControl>

Image

Imageは画像を表示するコントロールです。以下が例です。

 <Image Source="images/prota.png"/>
プロ太

画像ファイルを適切な場所へ配置する必要があります。配置方法については演習で詳しく解説します。

演習:様々なコントロールを使ったアプリ

作成するアプリの概要

主要コントロールを組み合わせて、以下の機能を持つ「リスト型メモ帳アプリ」を作成します。

  • アプリロゴを画面に表示
  • カテゴリを選択してメモを入力
  • 入力したメモ(カテゴリ付き)の一覧を表示
  • タブによる「メモ画面」と「設定画面」の切り替え
    (今回、設定画面はダミーです)

様々なカテゴリからピックアップした、以下のようなコントロールを使います。

  • Grid – 基本レイアウト
  • Button – メモ追加ボタン
  • TextBox – メモ入力欄
  • ListView – メモ一覧表示
  • ComboBox – カテゴリ選択
  • TabControl – 画面切り替え
  • Label – 各種ラベル表示
  • Image – アプリロゴ

以下の手順で作成します。

  • 手順1:画面作成(XAML)
  • 手順2:イベント作成(C#コードビハインド)
  • 手順3:ロゴ画像の配置とプロジェクトファイル修正
プロ美

画面(XAML)→イベント(C#コード)」のところは、WPFアプリ開発のいつもの手順だね!

手順1:画面作成(XAML)

WPFの新規プロジェクトを作成します。作成方法は以下の記事の手順2を参考にしてください。

【C#/WPF実践入門編(2)】はじめてのWPFアプリ作成 ~Hello WorldからButtonクリックまで~【XAML、コードビハインドの基本】 Windows Presentation Foundation (WPF) でのアプリ開発の基礎を、シンプルなHello Worldア...

MainWindow.xaml」を以下のように修正します。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!-- 上部:ロゴとタイトル -->
        <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,0,0,10">

            <!-- Image: アプリロゴ -->
            <Image Source="images/logo.png" Width="40" Height="40" Margin="0,0,10,0"/>

            <!-- Label: アプリタイトル -->
            <Label Content="リスト型メモ帳アプリ" FontSize="18" FontWeight="Bold" 
                VerticalAlignment="Center"/>

        </StackPanel>

        <!-- TabControl: メインエリア -->
        <TabControl Grid.Row="1">

            <!-- メモ入力・表示タブ -->
            <TabItem Header="メモ">
                <Grid Margin="10">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>

                    <!-- 入力エリア -->
                    <StackPanel Grid.Row="0" Margin="0,0,0,10">

                        <!-- Label: 入力ラベル -->
                        <Label Content="新しいメモ:" FontWeight="Bold"/>

                        <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
                            <!-- TextBox: メモ入力 -->
                            <TextBox x:Name="MemoTextBox" Width="180" Margin="0,0,10,0" 
                                  Text="ここにメモを入力"/>

                            <!-- ComboBox: カテゴリ選択 -->
                            <ComboBox x:Name="CategoryComboBox" Width="70" Margin="0,0,10,0">
                                <ComboBoxItem Content="仕事" IsSelected="True"/>
                                <ComboBoxItem Content="個人"/>
                                <ComboBoxItem Content="買い物"/>
                            </ComboBox>

                            <!-- Button: 追加ボタン -->
                            <Button Content="追加" Click="OnAddButtonClick"/>
                        </StackPanel>

                    </StackPanel>

                    <!-- ListView: メモ一覧 -->
                    <ListView x:Name="MemoListView" Grid.Row="1">
                        <ListViewItem Content="サンプルメモ1 (仕事)"/>
                        <ListViewItem Content="サンプルメモ2 (個人)"/>
                    </ListView>

                </Grid>
            </TabItem>

            <!-- 設定タブ -->
            <TabItem Header="設定">
                <StackPanel Margin="20">

                    <!-- Label: 設定タイトル -->
                    <Label Content="アプリ設定" FontSize="14" FontWeight="Bold"/>

                    <CheckBox Content="起動時にメモを自動読み込み" IsChecked="True" Margin="0,10,0,5"/>
                    <CheckBox Content="終了時に確認ダイアログを表示" IsChecked="False" Margin="0,5,0,10"/>

                </StackPanel>
            </TabItem>

        </TabControl>

    </Grid>
</Window>

これまで紹介してきたコントロールやプロパティを中心に使っています。ポイントは以下です。

  • Grid.RowDefinitions: Autoで上部のロゴ・タイトル領域を最小サイズに、*でTabControl領域を残り全体に配置
  • StackPanel: 横並び(Horizontal)でロゴ画像とタイトルラベルを配置
  • Image: ロゴ画像を表示
  • TabControl: メモタブと設定タブの2画面を切り替え可能に構成
  • ListView: 初期状態でサンプルメモを表示、後からC#コードで動的に項目追加
  • ComboBox: 「仕事」「個人」「買い物」の3つのカテゴリから選択可能、「仕事」を初期選択に設定

手順2:イベント作成(C#コードビハインド)

次に「MainWindow.xaml.cs」を以下のように修正します。

...
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    // イベントハンドラ: ボタンがクリックされたときに呼び出される
    private void OnAddButtonClick(object sender, RoutedEventArgs e)
    {
        // TextBox: 入力されたメモを取得
        string memo = MemoTextBox.Text;

        // ComboBox: 選択されたカテゴリを取得
        string? category = (CategoryComboBox.SelectedItem as ComboBoxItem)?.Content.ToString();

        if (!string.IsNullOrWhiteSpace(memo))
        {
            // ListView: 新しいメモを追加
            MemoListView.Items.Add($"{memo} ({category})");

            // TextBox: 入力欄をクリア
            MemoTextBox.Clear();
        }
    }
}
...

ポイントは以下です。

  • OnAddButtonClick: ボタンクリック時にTextBoxとComboBoxから値を取得し、ListViewに新しい項目を追加
  • 入力値の検証: string.IsNullOrWhiteSpaceで空文字チェックを行い、有効な入力のみ処理
  • UI更新: メモ追加後にTextBoxをクリアして次の入力に備える
  • ComboBoxの値取得: SelectedItemをComboBoxItemにキャストしてContentプロパティから文字列を取得

手順3:ロゴ画像配置とプロジェクトファイル修正

最後にロゴ画像ファイルを用意し、その画像ファイルがデバッグビルド時に、デバッグ用のバイナリファイルのフォルダへ自動で配置されるようにしましょう。

まず、WpfApp1プロジェクトフォルダ直下にimagesフォルダを作成し、そこへロゴ画像(ここではlogo.png)を配置します。

...
└─WpfApp1
    │  App.xaml
    │  App.xaml.cs
    │  AssemblyInfo.cs
    │  MainWindow.xaml
    │  MainWindow.xaml.cs
    │  WpfApp1.csproj
    │
    ├─images
    │      logo.png
...
プロ太

imagesフォルダ作成やロゴ画像の配置は、Windowsのファイルエクスプローラ上で直接行ってOKです!

次に、プロジェクトファイルを直接編集し、ビルド時にデバッグ用バイナリと同じフォルダにこのimagesフォルダが自動でコピーされるよう設定を追加します。

Visual Studioのソリューションエクスプローラで「WpfApp1(プロジェクト)」を選び、右クリックメニューを開きます。

「プロジェクトの編集」を選びます。

以下のように、「<ItemGroup>…</ItemGroup>」の記述を追加します。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net9.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

  <ItemGroup>
	<Content Include="images\*.*">
	  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
	</Content>
  </ItemGroup>

</Project>

これで、imagesフォルダがビルド時にデバッグ用バイナリが配置されたフォルダ(例:WpfApp1\bin\Debug\net9.0-windows)へコピーされるようになります。

プロ美

プロジェクトファイル(WpfApp1.csproj)の中身を、直接編集しているんだね!

ビルド後に、デバッグ用バイナリが配置されたフォルダ内を確認すると、imagesフォルダ(と中身の画像)がコピーされていることが確認できます。

C#におけるプロジェクト構成や、実行用バイナリファイルの配置などについては、以下でも触れて解説していますので、参考にしてください。

C#入門編(11)名前空間とファイル分割 ~Visual Studioでコードを整理整頓~ プログラムが規模を増すにつれ、その管理が徐々に難しくなってくると思います。 これは、プログラム内のクラスやメソッドが増え、それら...
プロ太

これで一通りできました!動かしてみましょう。

アプリを実行

アプリをデバッグ実行してみましょう。リストへのメモ追加がきます。

タブ切り替えで(ダミーですが、)設定も開けます。

プロ美

色々なコントロールを使ったアプリができたね!

プロ太

簡単なアプリではありますが、今回はWPFの様々な系統のコントロールの使い方・雰囲気を掴んでもらえればOKです!

まとめ

本記事では、WPFの主要コントロールを使った実践的なアプリ開発について学びました。

WPFのコントロールには以下の特徴と利点があります。

  • 豊富な種類:レイアウト、ボタン、選択、入力、データ表示など、10以上のカテゴリに分類される多様なコントロールが用意されている
  • 柔軟な組み合わせ:Gridなどのレイアウトコントロールと、Button、ListViewなどの機能コントロールを組み合わせて、複雑なUIを構築できる

リスト型メモ帳アプリの演習を通じて、以下のような様々な系統のコントロールを組み合わせて使う方法を学びました。

  • Grid(レイアウト系
  • Button(ボタン系
  • TextBox(入力系
  • Label(ユーザ情報系
  • ListView(データ表示系
  • ComboBox(選択系
  • TabControl(ナビゲーション系
  • Image(メディア系

ここまでで、XAML・C#コードビハインド、そしてレイアウトを含めた様々なコントロールの使い方といったWPFアプリ開発の基礎について学んでいきました。

次回は、WPFの特徴的な機能の1つである「データバインディング」について解説する予定です。

プロ太

引き続き、一緒にWPFアプリ開発を学んでいきましょう!

ABOUT ME
プロ太
●仕事:現在は個人事業主(メンター・情報発信等)、大手IT企業で技術者・マネージャ(15年以上)、大学の外部講師、学生時代は学習塾で非常勤講師(約4年間) ●博士(工学)の学位取得 ●高校生の頃に独学で始め、プログラミング歴20年以上 ●言語:C# 、Java、C/C++、Python、JavaScript/TypeScript等 ●分野:Webアプリ、テスト自動化、生成AI、デバッガ、コード解析、ドメイン特化言語

ご依頼・ご相談について

プログラミング学習のご相談、お仕事のご依頼については、
こちらのお問い合わせページをご確認ください。