【入門】WinForms × DataSet で作る「書籍管理アプリ」
〜保存・ロード機能を実装しよう〜
1. はじめに
「本のタイトルと著者、価格を入力して一覧化 → 保存 → 次回起動時に復元」
こんなシンプルなアプリを WinForms + DataSet で作ってみます。
この記事は 初心者向けで、以下の機能にしぼっています:
- DataGridView にデータを入力
- 保存ボタンでXMLに保存
- 起動時に自動で読み込み
短いコードで動作するので、C#とWinFormsの学習に最適です。
2. プロジェクトの作成
- Visual Studio を起動
- 「新しいプロジェクトの作成」を選択
- プロジェクトテンプレートから
- C# → Windows フォーム アプリ (.NET Framework) を選択
- プロジェクト名は BookManager にします

3. 画面デザイン(UI)
フォームに以下のコントロールを配置します。
- DataGridView : 書籍一覧 (bookDataGrid)
- TextBox : 書名 (bookName)、著者 (author)、価格 (price)
- Button : 「登録」(addButton)、 「削除」(removeButton)
配置例(イメージ):

DataGridView が上にあり、その下に「書名」「著者」「値段」の TextBox と「登録」「削除」ボタンを配置。
4. データセットの準備
- ソリューションエクスプローラーでプロジェクトを右クリック
- 「追加」→「新しい項目」

- 「データセット」を選び、名前を bookDataSet.xsd にします

次に DataSet デザイナが開きます。ここで「DataTable」を追加し、列を定義します。
- 列1: Title(string型)
- 列2: Author(string型)
- 列3: Price(int型)

DataSet デザイナ画面に DataTable を追加し、列「Title」「Author」「Price」を定義している画面。
5. コードの追加
Form1.cs に以下のコードを追加します。
using System;
using System.Data;
using System.IO;
using System.Windows.Forms;
namespace BookManager
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// 起動時にデータを読み込む
private void Form1_Load(object sender, EventArgs e)
{
LoadData();
}
// 終了時にデータを保存
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
SaveData();
}
// 登録ボタン
private void AddButtonClicked(object sender, EventArgs e)
{
bookDataSet.bookDataTable.AddbookDataTableRow(
bookName.Text,
author.Text,
int.Parse(price.Text));
bookName.Clear();
author.Clear();
price.Clear();
}
// 削除ボタン
private void RemoveButtonClicked(object sender, EventArgs e)
{
if (bookDataGrid.CurrentRow != null)
{
bookDataGrid.Rows.RemoveAt(bookDataGrid.CurrentRow.Index);
}
}
// 保存処理
private void SaveData(bool showMessage = false)
{
try
{
string path = GetDataFilePath();
bookDataSet.WriteXml(path, XmlWriteMode.WriteSchema);
if (showMessage) MessageBox.Show("保存しました。");
}
catch (Exception ex)
{
MessageBox.Show("保存に失敗しました: " + ex.Message);
}
}
// 読み込み処理
private void LoadData(bool showMessage = false)
{
try
{
string path = GetDataFilePath();
bookDataSet.bookDataTable.Clear();
if (File.Exists(path))
{
bookDataSet.ReadXml(path, XmlReadMode.ReadSchema);
if (showMessage) MessageBox.Show("読み込みました。");
}
}
catch (Exception ex)
{
MessageBox.Show("読み込みに失敗しました: " + ex.Message);
}
}
// 保存ファイルの場所(ユーザーごとのAppData)
private string GetDataFilePath()
{
string dir = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"BookManager");
Directory.CreateDirectory(dir);
return Path.Combine(dir, "BookData.xml");
}
}
}
方法① デザイナから登録(初心者向け)
- フォームデザイナを開く
- フォームをクリックして選択
- プロパティウィンドウの「イベント」タブ(⚡マーク)を選択
- Load の欄に Form1_Load と入力
- FormClosing の欄に Form1_FormClosing と入力

これで自動的に InitializeComponent(); の中に以下のコードが追加されます:
this.Load += new System.EventHandler(this.Form1_Load);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
方法② コードから手動登録(上級者向け)
Form1.cs のコンストラクタに以下を追加します。
public Form1()
{
InitializeComponent();
// イベントハンドラをコードで登録
this.Load += Form1_Load;
this.FormClosing += Form1_FormClosing;
}
こちらの方が イベントがどこで紐づいているかが見やすい というメリットがあります。
初学者向けまとめ
- Form1_Load は「起動時に処理を実行したい」場所
- Form1_FormClosing は「終了時に処理を実行したい」場所
- Visual Studio では「デザイナから登録」しておけば自動で結びつくので、まずはそちらがおすすめ
- 慣れてきたら「コードで登録」する方法も覚えると良い
処理の流れ
1.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
- Windows が用意している 「ユーザーごとのアプリデータ保存場所」 のパスを取得します。
- 例:
- Windows 10/11 の場合C:\Users\ユーザー名\AppData\Local
ここを使うことで、「誰が使っても、その人専用の保存先」にデータを置けます。
(プログラムをインストールしたフォルダに直接保存すると、権限の問題でエラーになりやすいのでNGです)
2. Path.Combine(…, “BookManager")
- 上で取った AppData\Local に “BookManager” フォルダ をくっつけています。
- 結果の例:C:\Users\ユーザー名\AppData\Local\BookManager
→ プロジェクト名と同じ名前のフォルダを作って、その中に保存するようにしています。
3. Directory.CreateDirectory(dir)
- 指定したフォルダがなければ 自動で作成 します。
- すでに存在していれば何もしません。
- これで「初回起動時にフォルダがなくてエラーになる」という問題を防いでいます。
4. return Path.Combine(dir, “BookData.xml");
- 最後に、BookManager フォルダの中に BookData.xml というファイル名を付けて返します。
- 例:C:\Users\ユーザー名\AppData\Local\BookManager\BookData.xml
これが「保存/読み込み」に使われるファイルのフルパスです。
ポイントまとめ
- ユーザーごとの専用領域に保存する → 権限の問題を避けられる
- プロジェクト用のフォルダを作成する → 他アプリとファイルが混ざらない
- パスを組み立てる処理を関数にまとめている → 保存/読み込み両方で使い回せる
例:実際の保存先パス
ユーザー名が taro の場合:
C:\Users\taro\AppData\Local\BookManager\BookData.xml
つまりこのメソッドは「環境依存しない、安全な保存先のパスを作って返す」ための便利関数です。

6. 実行してみよう
- プログラムを起動すると、空の DataGridView が表示されます
- テキストボックスに「書名・著者・価格」を入力して [登録] をクリック→ DataGridView に行が追加されます

- アプリを終了すると、ローカルの AppData に BookData.xml が保存されます

メモ帳で BookData.xml を開いた画面(XMLの中身が見える):
<?xml version="1.0" standalone="yes"?>
<BookDataSet xmlns="http://tempuri.org/BookDataSet.xsd">
<xs:schema id="BookDataSet" targetNamespace="http://tempuri.org/BookDataSet.xsd"
xmlns:mstns="http://tempuri.org/BookDataSet.xsd"
xmlns="http://tempuri.org/BookDataSet.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
attributeFormDefault="qualified" elementFormDefault="qualified">
<!-- スキーマ定義(テーブルの列構造) -->
<xs:element name="BookDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="bookDataTable">
<xs:complexType>
<xs:sequence>
<xs:element name="書名" type="xs:string" minOccurs="0" />
<xs:element name="著者" type="xs:string" minOccurs="0" />
<xs:element name="値段" type="xs:int" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<!-- 実データ部分 -->
<bookDataTable>
<書名>吾輩は猫である</書名>
<著者>夏目漱石</著者>
<値段>1200</値段>
</bookDataTable>
</BookDataSet>
- 再起動すると前回のデータが復元されます
7. まとめ
- DataSet + DataGridView で簡単に表形式データを管理できる
- 保存/ロードは WriteXml / ReadXml だけで実装可能
- 保存先は XML なので、中身を直接確認できる
ディスカッション
コメント一覧
まだ、コメントがありません