Microsoft Visual C# と SQLite で WPF 版日記アプリを作る

Microsoft Visual C# と SQL Server Compact で日記アプリを作るでは、データベースとしてSQL Server Compactを使用して日記アプリを作りました。
今回は、データベースとしてSQLiteを使用してデータベース組み込み型のWindows Presentation Foundation(以下、WPF)アプリを作ってみたいと思います。
実装した機能は日記一覧の表示と日記の登録というシンプルなものです。
日記の登録は別ウインドウを開いて登録するようにしました。
【完成したアプリ】

Note完成版のソースコードはhttps://github.com/mogcy/Diaryに置いてあります。Visual Studio 2019でビルドが可能です。

WPFの日記アプリプロジェクトの作成

[新しいプロジェクトの作成] より [WPFアプリ (.NET Framework)] を選択し新規プロジェクトを作成します。

プロジェクト名はDiaryとしました。

Visual Studio 2019にSQLiteをインストール

最初にVisual Studio 2019にSQLiteをインストールします。
[ソリューション エクスプローラー] の [Diary] プロジェクト項目の右クリックメニューより [NuGet パッケージの管理] をクリックします。

System.Data.SQLiteを選択してインストールします。

メインウインドウの設定

MainWindow.xamlに日記を一覧表示するためのデータグリッド(DiaryListViewGrid)、日記を見るボタン(ShowDiaryBtn)、日記を書くボタン(AddDiaryBtn)を配置します。

以下のように、MainWindow.xamlを設定します。
DataGrid.Columns内の2つ目のDataGridTextColumnWidth="*"は画面端いっぱいまでテーブルを表示するためです。この記述がないと右端に空白列が表示されてしまいます
また、DataGridではIsReadOnly="True"を追加します。これはテーブルの一番下に空白行(レコード追加用)が表示されるためです。読み取り専用にすることで空白行が表示されなくなります

<Window x:Class="Diary.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:Diary"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Button x:Name="AddDiaryBtn" Content="日記を書く" HorizontalAlignment="Left" Margin="30,0,0,30" Width="150" RenderTransformOrigin="0.562,0.131" Click="AddDiaryBtnClick" FontSize="22" MaxWidth="150" MaxHeight="50" MinWidth="150" MinHeight="50" Height="50" VerticalAlignment="Bottom"/>
        <Button x:Name="ShowDiaryBtn" Content="日記を見る" Margin="0,0,30,30" Click="ShowDiaryBtnClick" FontSize="22" RenderTransformOrigin="0.513,0.17" Width="150" MaxWidth="150" MaxHeight="50" Height="50" MinWidth="150" MinHeight="50" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
        <DataGrid x:Name="DiaryListViewGrid" Margin="30,30,30,100" ItemsSource="{Binding Mode=OneWay}" HorizontalGridLinesBrush="#FFD4D4D4" VerticalGridLinesBrush="#FFD4D4D4" IsReadOnly="True">
            <DataGrid.Columns>
                <DataGridTextColumn Header="日時" Binding="{Binding 'date'}" Width="100"/>
                <DataGridTextColumn Header="本文" Binding="{Binding 'text'}" Width="*"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

日記の登録用のウインドウの追加

日記の登録用のウインドウを追加するために、[ソリューション エクスプローラー] の [Diary] プロジェクト項目の右クリックメニューから [追加] > [ウインドウ] より新規ウインドウを作成し、テキストボックス(textBoxForAddDiary)、登録ボタン(AddDiaryData)、リセットボタン(RsetBtn)を配置します。
ウインドウの名前をAddDiaryWindowにします。

MainWindow.xamlとほぼ同じですが、AddDiaryWindow.xamlを以下のように設定します。

<Window x:Class="Diary.AddDiaryWindow"
        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:Diary"
        mc:Ignorable="d"
        Title="Window1" Height="450" Width="800">
    <Grid>
        <TextBox x:Name="textBoxForAddDiary" Margin="30,30,30,100" TextWrapping="Wrap"/>
        <Button x:Name="RsetBtn" Content="リセット" HorizontalAlignment="Left" Margin="30,0,0,30" RenderTransformOrigin="0.713,1.775" FontSize="22" Padding="10" Click="RsetBtnClick" Width="150" MaxWidth="150" MaxHeight="50" MinWidth="150" MinHeight="50" Height="50" VerticalAlignment="Bottom"/>
        <Button x:Name="AddDiaryData" Content="登録" Margin="0,0,30,30" FontSize="22" Padding="10" Click="AddDiaryDataClick" Width="150" MinWidth="150" MinHeight="50" MaxWidth="150" MaxHeight="50" Height="50" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
    </Grid>
</Window>

メインウインドウのコーディング

ここではメインウインドウでの、データベースとテーブルの作成、データベースから日記データをクエリしてデータグリッドに一覧表示するボタン、日記を登録するためのウインドウを呼び出すボタンをコーディングします。

SQLiteのデータベースとテーブルスキーマを作成するコードを記述

MainWindow.xaml.csにSQLiteとDataライブラリを使用するために以下を追加します。

using System.Data;
using System.Data.SQLite;

MainWindow()メソッドにSQLiteのデータベースDiaryDb.sqlite、およびテーブルdiaryを作成するためのコードを記述します。
作成するカラムは本文用のtextと日付用のdateの2つのみです。
※SQLiteにはDATETIMEなどの日付型が存在しないためTEXT型で作成しています。

        public MainWindow()
        {
            InitializeComponent();
            using (var conn = new SQLiteConnection("Data Source=DiaryDb.sqlite"))
            {
                // データベースに接続
                conn.Open();
                // コマンドの実行
                using (var command = conn.CreateCommand())
                {
                    // テーブルが存在しなければ作成する
                    // 日記テーブル
                    StringBuilder sb = new StringBuilder();
                    sb.Append("CREATE TABLE IF NOT EXISTS diary (");
                    sb.Append("text TEXT NOT NULL");
                    sb.Append("  , date TEXT NOT NULL");
                    sb.Append(")");

                    command.CommandText = sb.ToString();
                    command.ExecuteNonQuery();
                }
                // 切断
                conn.Close();
            }
        }

[日記を見る] ボタンのコードを記述

まず、[日記を見る] ボタン(ShowDiaryBtn)のプロパティのイベントハンドラー要素の項目でClickイベント欄にShowDiaryBtnClickを入力して保存し、[日記を見る] ボタンのクリックイベント用のメソッドShowDiaryBtnClickを生成します。

そして生成されたShowDiaryBtnClickメソッドに以下を記述します。

        private void ShowDiaryBtnClick(object sender, RoutedEventArgs e)
        {
            ShowDiaryToDataGrid();
        }

次に、データベースから日記一覧を取得してデータグリッドに表示するためのメソッドShowDiaryToDataGridを作成し、以下のように記述します。
なおデフォルトだと列を自動生成してしまい、DataGrid.Columnsで追加した列と、自動生成された列で重複して列が表示されてしまうため、列を自動生成しないようにAutoGenerateColumnsをfalseに設定します

        public void ShowDiaryToDataGrid()
        {
            using (SQLiteConnection conn = new SQLiteConnection("Data Source=DiaryDb.sqlite"))
            {
                // データベースに接続
                conn.Open();
                //日記一覧の表示
                using (DataSet dataSet = new DataSet())
                {
                    // データを取得
                    String sql = "SELECT date, text From diary ORDER BY date DESC LIMIT 1000";
                    SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter(sql, conn);
                    dataAdapter.Fill(dataSet);
                    //データグリッドに表示
                    this.DiaryListViewGrid.AutoGenerateColumns = false; //自動で列を作成しない(列が重複して表示されるため)
                    this.DiaryListViewGrid.DataContext = dataSet.Tables[0].DefaultView;
                }
                // 切断
                conn.Close();
            }
        }

[日記を書く] ボタンのコードを記述

[日記を書く] ボタンのクリックイベント用のメソッドAddDiaryBtnClickを生成し、以下のようにAddDiaryWindowを呼び出すコードを記述します。

        private void AddDiaryBtnClick(object sender, RoutedEventArgs e)
        {
            AddDiaryWindow adw = new AddDiaryWindow();
            adw.Show();
        }

日記の登録用のウインドウのコーディング

ここでは日記の登録用のウインドウでの、テキストボックスのデータをデータベースに挿入するボタン、テキストボックスのリセットボタンをコーディングします。

日記の登録用ウインドウのコードを記述

AddDiaryWindow.xaml.csMainWindow.xaml.csと同様に以下のusing文を記述します。

using System.Data;
using System.Data.SQLite;

AddDiaryWindowクラス内に日記データをデータベースに登録するためのAddDiaryToDbメソッドを生成し、以下のコードを記述します。

        private void AddDiaryToDb()
        {
            using (SQLiteConnection conn = new SQLiteConnection("Data Source=DiaryDb.sqlite"))
            {
                // データベースに接続
                conn.Open();
                //日記データの登録
                using (DataSet dataSet = new DataSet())
                {
                    // データを挿入
                    if (this.textBoxForAddDiary.Text != "") {
                        String sql = String.Format("INSERT INTO diary (date , text) VALUES ('{0}', '{1}')", DateTime.Now, this.textBoxForAddDiary.Text);
                        SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter(sql, conn);
                        dataAdapter.Fill(dataSet);
                    } else
                    {
                        MessageBox.Show("本文が入力されていません。", caption:"警告");
                    }
                }
                // 切断
                conn.Close();
            }
        }

[登録] ボタンのコードを記述

日記の [登録] ボタンのクリックイベント用のメソッドAddDiaryDataClickを作成し、以下のようにAddDiaryToDb()を呼び出し、その後ウインドウを閉じるためのコードを記述します。

        private void AddDiaryDataClick(object sender, RoutedEventArgs e)
        {
            AddDiaryToDb();
            this.Close();
        }

[リセット] ボタンのコードを記述

[リセット] ボタンのクリックイベント用のメソッドRsetBtnClickを作成し、以下を記述します。

        private void RsetBtnClick(object sender, RoutedEventArgs e)
        {
            this.textBoxForAddDiary.Text = "";
        }

最終的にソリューションエクスプローラーは以下のようになります。

ビルド

[ビルド] > [ソリューションのビルド] よりビルドし、アプリを実行して日記の登録、日記一覧の表示ができることを確認しましょう。

また、ウインドウを最大化した場合にも表示が崩れないかも忘れずに確認しておきましょう。

以上でC#とSQLiteでのWPF版日記アプリ作りは完了です。

追記(2020/11/01):
日付によるクエリ機能を追加しました。

日付によるクエリ機能の実装

DatePickerコントロールの配置

カレンダーによる日付入力のため、DatePickerコントロールを以下のように開始日(startDate)と終了日(endDate)用の2つを配置します。

DatePickerの初期値を現在日時に設定

DatePickerの初期値を現在日時に設定します。まず、MainWindow.xamlのWindow要素にxmlns:System="clr-namespace:System;assembly=mscorlib"属性を追記します。

次に、startDateとendDateの2つのDatePicker要素の属性にSelectedDate="{Binding Source={x:Static System:DateTime.Today}, Mode=OneTime}"を追加します。これを記述することで初期値に現在日時が設定されます。

DatePicker配置後のMainWindow.xamlは以下のようになります。

<Window x:Class="Diary.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:Diary"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
...
        <DatePicker x:Name="startDate" Margin="0,0,29,41" RenderTransformOrigin="0.946,0.542" SelectedDateFormat="Short" DisplayDate="2020-11-01" AutomationProperties.HelpText="開始日を指定してください" SelectedDate="{Binding Source={x:Static System:DateTime.Today}, Mode=OneTime}" Height="24" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="107"/>
        <DatePicker x:Name="endDate" Margin="29,0,0,41" RenderTransformOrigin="0.5,0.5" SelectedDateFormat="Short" AutomationProperties.HelpText="終了日を指定してください" SelectedDate="{Binding Source={x:Static System:DateTime.Today}, Mode=OneTime}" Height="24" VerticalAlignment="Bottom" Grid.Column="1" HorizontalAlignment="Left" Width="107"/>
        <Label Content="~" Margin="386,0,384,39" Grid.ColumnSpan="2" Height="26" VerticalAlignment="Bottom" Width="22" HorizontalAlignment="Center"/>
    </Grid>
</Window>

日記登録時のdate形式の変更

日付によるクエリの実装のために、AddDiaryWindow.xaml.csでデータベースのdateカラムに保存する日付の形式をDateTime形式(yyyy-MM-dd HH:mm:ss)に変更します。こうする理由は、この形式でなければ後で実施するdate()関数によるDate形式(yyyy-MM-dd)への変換が行えないためです。※その処理は後述します。

                        String sql = String.Format("INSERT INTO diary (date , text) VALUES ('{0}', '{1}')", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), this.textBoxForAddDiary.Text);

日付でクエリして日記を表示する処理の実装

日記一覧を表示するMainWindow.xaml.csで、DatePickerコントロールから日付データを取得するためのコードを追記します。DatePickerのデータをDateTime型に変換した上でフォーマットをDate形式(yyyy-MM-dd)に変更後、String型の変数startdateおよびenddateに保存しています。
                //日記一覧の表示
                using (DataSet dataSet = new DataSet())
                {
                    // 日付を取得
                    String startdate = new DateTime(startDate.SelectedDate.Value.Year, startDate.SelectedDate.Value.Month, startDate.SelectedDate.Value.Day).ToString("yyyy-MM-dd");
                    String enddate = new DateTime(endDate.SelectedDate.Value.Year, endDate.SelectedDate.Value.Month, endDate.SelectedDate.Value.Day).ToString("yyyy-MM-dd");
                    // データを取得
...

そして、その下の日記データ取得用のSQL文に、DatePickerから取得した日付の範囲でクエリできるように以下のWHERE句を挿入します。SQL上のdateカラムはDateTime形式で保存しているため、date()関数を用いてDate形式に変換した上でstartdateおよびenddateと比較しています。(DatePickerのデータをDate形式に変換したのはこのため)

                    // データを取得
                    String sql = String.Format("SELECT date, text FROM diary WHERE date(date) BETWEEN date('{0}') AND date('{1}') ORDER BY date DESC", startdate, enddate);

以上で、日付によるクエリ機能の実装は完了です。

完成版日記アプリのスクリーンショット

本格的にC#によるWindowsストアアプリ作りを学ぶなら、以下のチャールズ・ペゾルドの定番書籍がおすすめです。

オンラインによるプログラミングスクールの無料レッスンを受けてみたい方はTechAcademyの無料体験がおすすめです。

公開日:2019年05月26日

記事 > C#プログラミング > Microsoft Visual C# と SQLite で WPF 版日記アプリを作る

C#プログラミングの記事一覧

他の記事も見る

このページのトップに戻る