終了確認
何か入力があるときに終了しようとしたら確認するようにします。
Window
のClosing
イベントに以下の処理を書きます。
if (!string.IsNullOrEmpty(Memo.Text))
{
if (MessageBox.Show(
"入力がありますが、終了しますか?",
"確認",
MessageBoxButton.YesNo,
MessageBoxImage.Question) != MessageBoxResult.Yes)
{
// 終了をキャンセル
e.Cancel = true;
}
// 「はい」が押されたら普通に終了
}
非同期対応
ファイルを開くときと保存するときの処理を非同期で実行するようにします。
ファイル読み込み処理
OpenMenu_Click
の戻り値void
の前にasync
を付け足します。
StreamReader
のメソッド呼び出しを同期版のReadToEnd
から非同期版のReadToEndAsync
に変更します。
ReadToEndAsync
呼び出しにawait
を付けます。
修正前(同期版)はReadToEnd
が呼ばれたら終わるまで他の処理をせず待ち状態になります。
時間がかかる場合、応答なしで画面が固まってしまいます。
修正後(非同期版)では、ReadToEndAsync
が別スレッドで呼び出されるため、応答なしを防げます。
await
が付いているのでReadToEndAsync
が終わるまでOpenMenu_Click
の処理は先に進まず待機します。
ReadToEndAsync
が完了するとawait
の左側、Memo.Text
に結果を代入します。
ファイル読み込みの部分を別メソッドに切り出してみます。
以下のメソッドを定義し、await LoadFileToMemoAsync(dialog.FileName);
で呼び出します。
/// <summary>
/// ファイルを読み込んで内容を画面のTextBoxに設定
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
private async Task LoadFileToMemoAsync(string filePath)
{
using var reader = new StreamReader(
filePath,
encoding: Encoding.UTF8);
// 読み込んだ内容をTextBoxに設定
Memo.Text = await reader.ReadToEndAsync();
}
await
を使用するメソッドにはasync
を付けます。
非同期メソッド名は慣習的に末尾にAsync
を付けます。
非同期メソッドは戻り値がない場合はvoid
ではなくTask
にします(イベントハンドラだけ例外的に戻り値void
のままにします)。
戻り値がある場合はTask<戻り値の型>
にします。
ファイル保存処理
SaveAsMenu_Click
の戻り値void
の前にasync
を付け足します。
StreamWriter
のメソッド呼び出しを同期版のWrite
から非同期版のWriteAsync
に変更します。
WriteAsync
呼び出しにawait
を付けます。
設定ファイル
概要
初期値を設定ファイルから読み込むようにします。
NuGetパッケージのインストール
ソリューションエクスプローラーでプロジェクトを右クリックし、NuGetパッケージの管理
を選択します。
参照
を選択し、検索ボックスにextensions.config
を入力します。
Microsoft.Extensions.Configuration.Json
をインストールします。
もう1つ、Microsoft.Extensions.Configuration.Binder
もインストールします。
2つのパッケージがインストールされました。
設定ファイルの追加
ソリューションエクスプローラーでプロジェクトを右クリックし、追加
> 新しい項目
を選択します。
左のツリーからWeb
を選択し、JavaScript JSON 構成ファイル
を選択します。
名前
にappsettings.json
を入力し、追加
ボタンを押します。
↓↓↓↓↓
中身を以下のように書き換えます。
ウィンドウのタイトルと、起動時のウィンドウ高さ・幅です。
{
"Window": {
"Title": "簡易メモ帳",
"InitHeight": 300,
"InitWidth": 400
}
}
メニューのファイル
> 名前を付けて appsettings.json を保存
を選択します。
上書き保存
ボタン右の▼
からエンコード付きで保存
を選択します。
上書き確認ではい
を選択します。
エンコード
にUnicode (UTF-8シグネチャなし) - コードページ 65001
を選択します。
OK
を選択します。
appsettings.json
のプロパティで出力ディレクトリにコピー
を新しい場合はコピーする
に設定します。
これでプロジェクト直下のappsettings.json
(元ファイル)がbin
フォルダ配下にもコピーされるようになります。
ロジックの記述
App.xaml.cs
に定数を追加します。
public partial class App : Application
{
/// <summary>
/// 設定ファイル名
/// </summary>
public const string AppSettingsFile = "appsettings.json";
}
Window
のSourceInitialized
イベントに以下を書きます。
try
{
LoadAppSettings();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
設定ファイルから取得したウィンドウのサイズを適用するため、Loaded
より前の段階で発生するSourceInitialized
イベントを使用します。
LoadAppSettings
のメソッドの生成をし、以下を書きます。
const double MinWindowSize = 150;
const double MaxWindowSize = 800;
const double DefWindowSize = 400;
IConfigurationRoot config = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile(App.AppSettingsFile, optional: true, reloadOnChange: false)
.Build();
// 設定読み込み
IConfigurationSection section = config.GetSection("Window");
Title = section.GetValue<string>("Title", "メモ");
double h = section.GetValue<double>("InitHeight", DefWindowSize);
double w = section.GetValue<double>("InitWidth", DefWindowSize);
// ウィンドウ高さ設定
Height = (h is < MinWindowSize or > MaxWindowSize)
? DefWindowSize
: h;
// ウィンドウ幅設定
Width = (w is < MinWindowSize or > MaxWindowSize)
? DefWindowSize
: w;
AddJsonFile
の引数optional
にtrue
を設定すると、設定ファイルが存在しなくても例外が発生しません。
設定値読み込み処理のGetValue
の1番目の引数は設定項目のキーで、2番目の引数は読み込めなかったときの初期値です。
📘他の書き方(config)
IConfigurationRoot
のconfig
を作るまでの処理は以下のようにも書けます。
IConfigurationBuilder cfgBuilder = new ConfigurationBuilder();
cfgBuilder.SetBasePath(AppContext.BaseDirectory);
cfgBuilder.AddJsonFile(App.AppSettingsFile, optional: true, reloadOnChange: false);
IConfigurationRoot config = cfgBuilder.Build();
📘他の書き方(Height, Width)
Height
, Width
の設定は以下のようにも書けます。
// ウィンドウ高さ設定
if (h < MinWindowSize ||
h > MaxWindowSize)
{
Height = DefWindowSize;
}
else
{
Height = h;
}
// ウィンドウ幅設定
if (w < MinWindowSize ||
w > MaxWindowSize)
{
Width = DefWindowSize;
}
else
{
Width = w;
}
実行
実行してみます。
タイトルのテキストが設定ファイルのものに変わりました。
いったん終了し、実行ファイルのある場所のappsettings.json
を書き換え保存し、Memo.exe
を起動してみます。
復習ポイント
- 終了確認
- async/await
- NuGet
- 設定ファイルの読み込み