Windows GUIプログラミング入門13 リストビュー(2)、メニュー

  • 3
    いいね
  • 0
    コメント

はじめに

前回に引き続き、ListViewを使います。
今回はCSVを読み込ませてListViewに表示します。

キーワード:ListView, Menu, OpenFileDialog, CSV

[注意]
これまでの回で説明済みの操作方法等は、説明を省略したり簡略化している場合があります。

開発環境

  • Windows 10 (バージョン1703)
  • Visual Studio Community 2017

作ってみる

CSVデータ

郵便番号のCSVデータをListViewに表示するプログラムを作ります。
今回使うデータはこちら。
郵便番号データダウンロード - 日本郵便
CSVデータの仕様はこちら。
郵便番号データの説明 - 日本郵便

プロジェクトにクラスを追加します。
名前はZipRecord.csにします。
これがCSV1件分に対応します。

ZipRecord.cs
/// <summary>
/// 郵便番号データ
/// </summary>
public class ZipRecord
{
    /// <summary>
    /// 全国地方公共団体コード
    /// </summary>
    public string Code { get; set; }

    /// <summary>
    /// (旧)郵便番号
    /// </summary>
    public string ZipOld { get; set; }

    /// <summary>
    /// 郵便番号
    /// </summary>
    public string Zip { get; set; }

    /// <summary>
    /// 都道府県名カナ
    /// </summary>
    public string StateKana { get; set; }

    /// <summary>
    /// 市区町村名カナ
    /// </summary>
    public string CityKana { get; set; }

    /// <summary>
    /// 町域名カナ
    /// </summary>
    public string TownKana { get; set; }

    /// <summary>
    /// 都道府県名
    /// </summary>
    public string State { get; set; }

    /// <summary>
    /// 市区町村名
    /// </summary>
    public string City { get; set; }

    /// <summary>
    /// 町域名
    /// </summary>
    public string Town { get; set; }

    /// <summary>
    /// 一町域が二以上の郵便番号で表される場合の表示
    /// </summary>
    /// <remarks>
    /// 「1」は該当、「0」は該当せず
    /// </remarks>
    public string Flag1 { get; set; }

    /// <summary>
    /// 小字毎に番地が起番されている町域の表示
    /// </summary>
    /// <remarks>
    /// 「1」は該当、「0」は該当せず
    /// </remarks>
    public string Flag2 { get; set; }

    /// <summary>
    /// 丁目を有する町域の場合の表示
    /// </summary>
    /// <remarks>
    /// 「1」は該当、「0」は該当せず
    /// </remarks>
    public string Flag3 { get; set; }

    /// <summary>
    /// 一つの郵便番号で二以上の町域を表す場合の表示
    /// </summary>
    /// <remarks>
    /// 「1」は該当、「0」は該当せず
    /// </remarks>
    public string Flag4 { get; set; }

    /// <summary>
    /// 更新の表示
    /// </summary>
    /// <remarks>
    /// 「0」は変更なし、「1」は変更あり、「2」廃止(廃止データのみ使用)
    /// </remarks>
    public string Flag5 { get; set; }

    /// <summary>
    /// 変更理由
    /// </summary>
    /// <remarks>
    /// 「0」は変更なし、「1」市政・区政・町政・分区・政令指定都市施行、
    /// 「2」住居表示の実施、「3」区画整理、「4」郵便区調整等、
    /// 「5」訂正、「6」廃止(廃止データのみ使用)
    /// </remarks>
    public string Flag6 { get; set; }
}

メニュー・リストビュー

Gridを真ん中ぐらいで分割して上の段にMenuを、下の段にListViewを配置します。
wbg13-01.png

Menuのプロパティ、Itemsの「...」からコレクションエディターを表示します。
wbg13-02.png

MenuItemを2つ作ります。
1つ目のHeaderは「ファイル(_F)」、2つ目は「編集(_E)」にします。
wbg13-03.png

追加後。
wbg13-04.png

「ファイル」のMenuItemを選択し、Itemsのコレクションエディターを開きます。
wbg13-05.png

MenuItemで「開く(_O)...」、
Separator
MenuItemで「終了(_X)」を追加します。
wbg13-06.png

追加後。
wbg13-07.png

「編集」メニューを選択し、今度は「MenuItemの追加」で項目を追加します。
wbg13-08.png

Headerは「クリア(_C)」にします。
wbg13-09.png

「開く」メニューに名前を付けます。
wbg13-10.png

openMenuにします。
wbg13-11.png

同様に「終了」メニューはexitMenuに、「クリア」メニューはclearMenuにします。

<MenuItem Header="ファイル(_F)">
    <MenuItem x:Name="openMenu" Header="開く(_O)..."/>
    <Separator/>
    <MenuItem x:Name="exitMenu" Header="終了(_X)"/>
</MenuItem>
<MenuItem Header="編集(_E)">
    <MenuItem x:Name="clearMenu" Header="クリア(_C)"/>
</MenuItem>

デザイナでGridの上段をAutoに、下段をStarに設定(やり方は第5回参照)し、
MenuListViewのレイアウトを「すべてリセット」(やり方は第7回参照)します。

ウィンドウ

WindowTitle郵便番号一覧に、ResizeModeCanResizeWithGripに設定します。
wbg13-12.png

表示とデータの関連付け

ListViewとCSVデータの入れ物を関連付けます。

MainWindow.xaml.cs
public partial class MainWindow : Window
{
    // 郵便番号データのコレクション
    public System.Collections.ObjectModel.ObservableCollection<ZipRecord> ZipRecords { get; set; }

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public MainWindow()
    {
        InitializeComponent();

        // 郵便番号データのコレクションを初期化
        this.ZipRecords = new System.Collections.ObjectModel.ObservableCollection<ZipRecord>();
        // 関連付け
        listView.DataContext = this.ZipRecords;
    }
}

XamlでListViewを選択し、プロパティのItemsSource横のメニューから「データバインドの作成」を選択し、「バインドの種類」に「データコンテキスト」を選択します。

リストビューの列

ListViewの列を設定します。

ListViewColumnsのコレクションエディターを開きます。
wbg13-13.png

GridViewColumnsを以下のように設定します。

DisplayMemberBinding Header
Zip 郵便番号
State 都道府県名
City 市区町村名
CityKana 市区町村名カナ
Town 町域名
TownKana 町域名カナ

DisplayMemberBindingは横のメニューから「データバインドの作成」を選択し、
wbg13-14.png

「バインドの種類」に「データコンテキスト」を選択し、「パス」の欄に表示元データ(ZipRecordクラス)の項目名を入力します。
wbg13-15.png

ここまででListViewは以下のようになります。

<ListView x:Name="listView" Grid.Row="1" ItemsSource="{Binding Mode=OneWay}">
    <ListView.View>
        <GridView>
            <GridViewColumn DisplayMemberBinding="{Binding Zip}" Header="郵便番号"/>
            <GridViewColumn DisplayMemberBinding="{Binding State}" Header="都道府県名"/>
            <GridViewColumn DisplayMemberBinding="{Binding City}" Header="市区町村名"/>
            <GridViewColumn DisplayMemberBinding="{Binding CityKana}" Header="市区町村名カナ"/>
            <GridViewColumn DisplayMemberBinding="{Binding Town}" Header="町域名"/>
            <GridViewColumn DisplayMemberBinding="{Binding TownKana}" Header="町域名カナ"/>
        </GridView>
    </ListView.View>
</ListView>

wbg13-16.png

CSV読み込み

CSV読み込みの機能を使うために、参照の追加でMicrosoft.VisualBasicを追加します。

コードビハインドにCSVを読み込むメソッドを作ります。

MainWindow.xaml.cs
/// <summary>
/// CSVファイル読み込み
/// </summary>
/// <param name="filePath">CSVファイルパス</param>
private void ReadCsv(string filePath)
{
    this.ZipRecords.Clear();

    var parser =
        new Microsoft.VisualBasic.FileIO.TextFieldParser(filePath, Encoding.Default);
    using (parser)
    {
        // 「,」区切りのデータとして処理する
        parser.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited;
        parser.SetDelimiters(",");

        try
        {
            // ファイルの終わりまで繰り返す
            while (parser.EndOfData == false)
            {
                // 一行分読み込み
                string[] buf = parser.ReadFields();

                this.ZipRecords.Add(new ZipRecord
                {
                    Code = buf[0],
                    ZipOld = buf[1],
                    Zip = buf[2],
                    StateKana = buf[3],
                    CityKana = buf[4],
                    TownKana = buf[5],
                    State = buf[6],
                    City = buf[7],
                    Town = buf[8],
                    Flag1 = buf[9],
                    Flag2 = buf[10],
                    Flag3 = buf[11],
                    Flag4 = buf[12],
                    Flag5 = buf[13],
                    Flag6 = buf[14],
                });

            }
        }
        catch
        {
            throw new Exception("CSV読み込みでエラー!");
        }
    }
}

ファイルを開く

メニューから「開く」を選択した時の処理を作ります。
ドキュメントアウトラインで「openMenu」を選択し、画面の「開く」メニューをダブルクリックし、以下を入力します。
wbg13-17.png

/// <summary>
/// メニュー「開く」
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void openMenu_Click(object sender, RoutedEventArgs e)
{
    var dlg = new Microsoft.Win32.OpenFileDialog();

    // フィルタ設定
    dlg.Filter = "CSVファイル(*.csv)|*.csv|テキストファイル(*.txt)|*.txt|全てのファイル(*.*)|*.*";
    // フィルタの1番目(CSV)を選択状態にする
    dlg.FilterIndex = 1;

    // ファイルを開くダイアログ表示
    if (dlg.ShowDialog() == true)
    {
        this.IsEnabled = false;

        // CSV読み込み
        ReadCsv(dlg.FileName);

        this.IsEnabled = true;
    }
}

その他のメニュー処理

メニュー項目の「終了」、「クリア」も同様に処理を作ります。

/// <summary>
/// メニュー「終了」
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void exitMenu_Click(object sender, RoutedEventArgs e)
{
    // プログラム終了
    this.Close();
}

/// <summary>
/// メニュー「クリア」
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void clearMenu_Click(object sender, RoutedEventArgs e)
{
    // 一覧をクリア
    this.ZipRecords.Clear();
}

動かしてみる

起動してみます。
wbg13-18.png

メニューの「ファイル」 - 「開く」でファイル選択ダイアログを表示します。
拡張子のフィルタの初期選択値はCSVになっています。
wbg13-19.png

こちらからダウンロードしたCSVを読み込ませてみます。
wbg13-20.png

表示されました。
wbg13-21.png

メニューの「編集」 - 「クリア」を選択すると一覧がクリアされ、「ファイル」 - 「終了」を選択するとプログラムが終了します。

おしまい

※次回はこのプログラムをもう少し改善します。まだ捨てないでください。


<< 最初の記事   < 前の記事   次の記事 >