【C#入門】WPFでGUIを作る方法(DataGrid、ComboBox、ListBoxなど)

こんにちは!フリーランスの長野です。

WPFって使ってますか?WPFはC#でGUIを作成する場合に使うテンプレートの一種です。

WPFはGUIを柔軟にカスタマイズできるなどの点で便利なGUI開発ライブラリです。この記事では、WPFについて

  • WPFとは
  • WPFの特徴
  • WPFの使い方

といった基本的な内容から、

  • コントロールの使い方

など実用的な使い方についても解説していきます。今回はWPFについて、使い方をわかりやすく解説します。

目次

WPFとは

WPFとはWindows Presentation Foundationの略称で.NET Frameworkに含まれるGUI開発ライブラリです。.NET Frameworkに含まれていますので、C#やVisual Basicでも使うことができます。

GUI開発ライブラリですので、ボタンやテキストボックスなどといったコントロールを使ったWindowsアプリケーションを作成することができます。

GUI開発ライブラリと言えば、Windowsフォームもよく使われていますが、WindowsフォームはC言語などで使われるWin32 APIを継承しているのに対して、WPFはWin32 APIとは無関係で新たに実装されたGUI開発ライブラリです。

WPFはUI(ユーザー・インターフェイス)要素に拡大・縮小/回転などを掛けることができて、柔軟にカスタマイズできるなどの点で便利なGUI開発ライブラリです。

XAML、XMLについて

WPFはXAML(Extensible Application Markup Language)と呼ばれる、XML形式の言語を用いてUIを記述します。

XML形式の言語ですので、HTMLに似た感覚で外観デザインを開発することができます。外観デザインに関する部分をXAML言語で記述し、処理などのロジックをC#で記述します。

外観デザインと処理などのロジックを分けることで、デザイナーとアルゴリズム開発者とで分業・協業がやりやすくなっています。

WPFの特徴

WPFには2つの大きな特徴があります。BindingとMVVMパターンです。

それぞれについて詳しくみていきましょう。

Bindingについて

WPFにはデータ・バインディングという機能があります。これは表示するデータに不整合がないか検証する機能と外観デザインとを分離する仕組みです。

データ・バインディングでは、外観デザインには「ここにはこのデータを表示する」という目印を入れるだけで、実際のデータは別のファイルから提供します。

テキストボックスに文字列を表示する例でWindowsフォームと比較してみましょう。Windowsフォームでの例:

textBox.Text = “Hello”;

WPFでの例:

MainWindow.xaml:

<TextBox Text=”{Binding Path=Txt}”>

ViewModel.cs:

public class ViewModel {
    public string Txt { get; set; } = "Hello";
}

このようにWPFでは、外観デザインの記述とデータの処理を別のファイルに分けることができます。

上記の例は簡単な内容のため、かえって不便に思えるかもしれませんが、外観デザインに多くのデータを表示させる必要がある場合などに、複数人での作業を分業・協業しやすくなるので便利です。

MVVMパターンについて

WPFではMVVMパターンと呼ばれる設計思想に沿ってGUIを作成することができます。MVVMパターンはUIを持つアプリケーションを実装する際のデザインパターンのことです。MVVMパターンとはModel-View-ViewModelパターンの略称です。

モデル、ビュー、ビューモデルの3つの部分に分割して実装します。モデルとは、データの不整合を検証する処理やデータベースとのデータのやりとりを実装する部分です。ビューとは、外観デザインを実装する部分です。

ビューモデルとは、ビューを描画するためのデータの保持と、ビューからの入力をモデルに伝達する部分になります。

WPFの場合XAMLファイルがビューにあたり、バインディングのパス指定先を記述したcsクラスファイルがビューモデルにあたります。

WPFの使い方

それでは、実際にWPFの使い方をみていきましょう。Visual Studioを使ってWPFを使う方法についてご紹介します。

まず、Visual Studioで「新しいプロジェクト」を作成します。
c#_wpf01

「Visual C#」→「Windows」→「クラシックデスクトップ」→「WPFアプリケーション」を選択し、アプリケーション名を入力して「OK」ボタンをクリックします。
c#_wpf02

「MainWindow.xaml」と「MainWindow.xaml.cs」が自動で作成され、WPFを使うことができるようになりました。
c#_wpf03

コントロールの使い方

WPFではボタン、テキストボックスなどGUIで使用する部品が「ツールボックス」にあらかじめ用意されています。

「MainWindow.xaml」タブを選択し有効にすることで、「ツールボックス」から各コントロールを使うことができます。それでは各コントロールの使い方についてみていきましょう。

DataGridの使い方

DataGridコントロールは、表形式のデータを表示するために使われます。

DataGridコントロールは「ツールボックス」の「コモンWPFコントロール」に用意されています。

c#_wpf04

「DataGrid」をクリックし、「MainWindow.xaml」のデザインの「Window」へドラッグ&ドロップすることで使えるようになります。

XAMLファイルには自動でGridタグ、DataGridタグが記述されています。

c#_wpf05

それでは、DataGridコントロールでデータを表示しましょう。まず、データを格納するクラスを作成します。

ここでは、Testクラスを作成します。Test.cs:

public class Test {
        public string Subj { get; set; }
        public int Points { get; set; }
        public string Name { get; set; }
        public string ClassName { get; set; }
}

このクラスのリストを作成するTestListクラスを作成します。

TestList.cs:

using System.Collections.ObjectModel;

public class TestList {
        // バインディングの指定先プロパティ
        public ObservableCollection<Test> Data { get; }

        // コンストラクタ(データ入力)
        public TestList() {
            Data = new ObservableCollection<Test> {
                new Test { Subj="国語", Points=90, Name="田中 一郎", ClassName="A" },
                new Test { Subj="数学", Points=50, Name="鈴木 二郎", ClassName="A" },
                new Test { Subj="英語", Points=90, Name="佐藤 三郎", ClassName="B" }
            };
        }       
 }

MainWindowクラスのコンストラクタでTestListクラスをインスタンス化します。

MainWindow.xaml.cs:

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

            this.DataContext = new TestList();
        }
}

XAMLファイルでは、DataGridコントロールのItemsSourceプロパティに格納する値を取得するためにバインディングを使っています。

MainWindowクラスのコンストラクタでTestListクラスをインスタンス化しているので、TestListクラスのDataプロパティから取得できています。MainWindow.xaml(一部のみ):

<DataGrid ItemsSource="{Binding Path=Data}" x:Name="dataGrid" />

実行結果:
c#_wpf06

ComboBoxの使い方

ComboBoxコントロールはリストから値を選択する場合に使用します。ComboBoxコントロールもDataGridコントロールと同じようにして、「ツールボックス」からドラッグ&ドロップすることで使えるようになります。

XAMLファイルには自動でComboBoxタグが記述されます。それでは、ComboBoxコントロールで選択リストを表示しましょう。

まず、リストを格納するクラスを作成します。ここでは、PrefListクラスを作成します。PrefList.cs:

using System.Collections.ObjectModel;

public class PrefList {
        public ObservableCollection<string> Data { get; }
        public PrefList() {
            Data = new ObservableCollection<string>();
            Data.Add("北海道");
            Data.Add("青森県");
            Data.Add("岩手県");
            Data.Add("秋田県");
        }
}

MainWindowクラスのコンストラクタでPrefListクラスをインスタンス化します。

MainWindow.xaml.cs:

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

            this.DataContext = new PrefList();
        }
}

XAMLファイルでは、ComboBoxコントロールのItemsSourceプロパティに格納する値を取得するためにバインディングを使っています。

MainWindowクラスのコンストラクタでPrefListクラスをインスタンス化しているので、PrefListクラスのDataプロパティから取得できています。MainWindow.xaml(一部のみ):

<ComboBox ItemsSource="{Binding Path=Data}" x:Name="comboBox" />

実行結果:
c#_wpf07

Gridの使い方

Gridコントロールは、テーブルレイアウトを行うために使います。行と列を定義して、要素を配置する位置を決めることができます。

Gridコントロールも同じようにして、「ツールボックス」からドラッグ&ドロップすることで使えるようになります。XAMLファイルには自動でGridタグが記述されます。

それではウィンドの行、列それぞれを2分割してみましょう。

ShowGridLinesプロパティの値をTrueに設定して、グリッドの点線を表示しています。MainWindow.xaml(一部のみ):

<Grid ShowGridLines="True" >
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
</Grid>

実行結果:
c#_wpf08

ListViewの使い方

ListViewコントロールも表形式のデータを表示するために使われます。ListViewコントロールも同じようにして、「ツールボックス」の「すべてのWPFコントロール」からドラッグ&ドロップすることで使えるようになります。

XAMLファイルには自動でListViewタグ、ListView.Viewタグ、GridViewタグ、GridViewColumnタグが記述されます。それでは、ListViewコントロールでデータを表示しましょう。

GridViewコントロールを使う場合と同様です。まず、データを格納するクラスを作成します。ここでは、Testクラスを作成します。Test.cs:

public class Test {
        public string Subj { get; set; }
        public int Points { get; set; }
        public string Name { get; set; }
        public string ClassName { get; set; }
}

このクラスのリストを作成するTestListクラスを作成します。

TestList.cs:

using System.Collections.ObjectModel;

public class TestList {
        // バインディングの指定先プロパティ
        public ObservableCollection<Test> Data { get; }

        // コンストラクタ(データ入力)
        public TestList() {
            Data = new ObservableCollection<Test> {
                new Test { Subj="国語", Points=90, Name="田中 一郎", ClassName="A" },
                new Test { Subj="数学", Points=50, Name="鈴木 二郎", ClassName="A" },
                new Test { Subj="英語", Points=90, Name="佐藤 三郎", ClassName="B" }
            };
        }       
 }

MainWindowクラスのコンストラクタでTestListクラスをインスタンス化します。

MainWindow.xaml.cs:

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

            TestList testList = new TestList();
            listView.DataContext = testList.Data;
        }
}

XAMLファイルでは、ListViewコントロールのItemsSourceプロパティに格納する値を取得するためにバインディングを使っています。

MainWindowクラスのコンストラクタでTestListクラスをインスタンス化しているので、TestListクラスのDataプロパティから取得できています。MainWindow.xaml(一部のみ):

<ListView ItemsSource="{Binding}" x:Name="listView" >
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="教科" DisplayMemberBinding="{Binding Path=Subj}" Width="50"/>
                    <GridViewColumn Header="点数" DisplayMemberBinding="{Binding Path=Points}" Width="50"/>
                    <GridViewColumn Header="氏名" DisplayMemberBinding="{Binding Path=Name}" Width="100"/>
                    <GridViewColumn Header="クラス名" DisplayMemberBinding="{Binding Path=ClassName}" Width="50"/>
                </GridView>
            </ListView.View>
</ListView>

実行結果:
c#_wpf09

ListBoxの使い方

ListBoxコントロールもリストから値を選択する場合に使用します。ListBoxコントロールも同じようにして、「ツールボックス」からドラッグ&ドロップすることで使えるようになります。

XAMLファイルには自動でListBoxタグが記述されます。それでは、ListBoxコントロールで選択リストを表示しましょう。

まず、リストを格納するクラスを作成します。ここでは、PrefListクラスを作成します。PrefList.cs:

using System.Collections.ObjectModel;

public class PrefList {
        public ObservableCollection<string> Data { get; }
        public PrefList() {
            Data = new ObservableCollection<string>();
            Data.Add("北海道");
            Data.Add("青森県");
            Data.Add("岩手県");
            Data.Add("秋田県");
        }
}

MainWindowクラスのコンストラクタでPrefListクラスをインスタンス化します。

MainWindow.xaml.cs:

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

            this.DataContext = new PrefList();
        }
}

XAMLファイルでは、ListBoxコントロールのItemsSourceプロパティに格納する値を取得するためにバインディングを使っています。

MainWindowクラスのコンストラクタでPrefListクラスをインスタンス化しているので、PrefListクラスのDataプロパティから取得できています。MainWindow.xaml(一部のみ):

<ListBox ItemsSource="{Binding Path=Data}" x:Name="listBox" />

実行結果:
c#_wpf10

TextBoxの使い方

TextBoxコントロールは文字列を表示または取得するために使用します。TextBoxコントロールも同じようにして、「ツールボックス」からドラッグ&ドロップすることで使えるようになります。

XAMLファイルには自動でTextBoxタグが記述されます。それでは、TextBoxコントロールで文字列を表示しましょう。

まず、文字列を格納するクラスを作成します。ここでは、ViewModelクラスを作成します。ViewModel.cs:

public class ViewModel {
        public string Txt { get; set; } = "Hello";
}

MainWindowクラスのコンストラクタでViewModelクラスをインスタンス化します。

MainWindow.xaml.cs:

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

            this.DataContext = new ViewModel();
        }
}

XAMLファイルでは、TextBoxコントロールのTextプロパティに格納する値を取得するためにバインディングを使っています。

MainWindowクラスのコンストラクタでViewModelクラスをインスタンス化しているので、ViewModelクラスのTxtプロパティから取得できています。

MainWindow.xaml(一部のみ):

<TextBox Text="{Binding Txt}" x:Name="textBox" />

実行結果:
c#_wpf11

まとめ

ここではWPFについて説明しました。

WPFはGUIを柔軟にカスタマイズできる、GUIのデザインとデータの処理を分離しやすいなどの点で便利なGUI開発ライブラリです。

使いこなすことができるように、この記事を何度も参考にして下さいね!

この記事を書いた人

熊本在住のフリープログラマ兼ライターです。C/C++/C#、Java、Python、HTML/CSS、PHPを使ってプログラミングをしています。専門は画像処理で最近は機械学習、ディープラーニングにはまっています。幅広くやってきた経験を活かしてポイントをわかりやすくお伝えしようと思います。
お問合せはこちらでも受け付けています。
info@sss-lab.com

目次