ListViewのデータソースとして使用しているリスト型のデータをTSV(タグ区切りの値)としてファイルに保存します。
再利用性の高い機能は、コードを独立させて再利用性を高めたいのですが、データスコープの問題があるので、実際に考えるとどのように分割するのか、プログラム全体を見直す必要があります。
しかし、今回は、再利用性は、考えず、最低限動作するコードを考えてみることにします。
これまでのコードに、リストを保存、そして、読み込むUIとコードを追加します。
ListViewのデータソースとして使用していても、実態は、複数のデータ・メンバを持つクラスのリスト型(ここでは、ObservableCollectionクラス)配列です。行うことは、単純に、それぞれのデータメンバを取り出して、ファイルに書き込むだけです。
UIに「リスト保存」ボタンを設置し、クリックイベントを追加します。クリックイベントに、ListViewのデータソースとして利用しているObservableCollection型のクラスの内容をTSV形式で、ファイルに保存するコードを記述します。
List型のデータの中身を取り出すには、foreachループを使います。
ObservableCollection型のリストは、以下のように定義しています。
ObservableCollection<SerchReplacePair> SerchReplacePairs = new ObservableCollection<SerchReplacePair>();
public void SetInitialList()
{
SerchReplacePairs.Add
(new SerchReplacePair()
{
SerchString = "検索",
ReplaceString = "置換"
});
SerchReplacePairs.Add
(new SerchReplacePair()
{
SerchString = "犬",
ReplaceString = "猫"
});
// ListViewのItemSourceに指定する
ReplaceList.ItemsSource = SerchReplacePairs;
}
foreachループで取り出して、ファイルに保存します。
private void ListSaveButton_Click(object sender, RoutedEventArgs e)
{
// 置換リストを保存する
// 保存対象のリスト SerchReplacePairs
// パスとファイル名
string filePath = @"H:\C#プロジェクト\ReplacePair.tsv";
// using文を使ってファイルをクローズするコード
using (StreamWriter writer = new StreamWriter(filePath))
{
foreach(SerchReplacePair n in SerchReplacePairs)
{
// ファイルに書き込む
writer.WriteLine(n.SerchString + "\t" +n.ReplaceString);
}
}
}
複数のデータ・メンバを持つクラスのリスト型(ここでは、ObservableCollectionクラス)配列から、それぞれの値を取り出す操作は、一度理解してしまえば簡単なのですが、基本的すぎて、項目としては、ほとんどコード例として取り上げられていません。その上、キーワード検索で見つけるのも困難です。そのため、最初に使うときに、探し回るのは仕方ないと考え、覚えてしまいましょう。また、"\t"は、タブを表します。
ファイルの保存先をUIで指定できるようにする
先程のコードは、保存先が固定です。
UIから、保存先を選択できるように変更します。
パスとファイル名を格納する変数をテキストボックに格納し、使用する際は、そのテキストボックスの値を使用します。
public MainWindow()
{
InitializeComponent();
SetInitialList();
// パスとファイル名を設定
ReplacListBox.Text = @"H:\C#プロジェクト\ReplacePair.tsv";
}
private void ListSaveButton_Click(object sender, RoutedEventArgs e)
{
// 置換リストを保存する
// 保存対象のリスト SerchReplacePairs
// using文を使ってファイルをクローズするコード
// ファイル名は、テキストボックスから取得する
using (StreamWriter writer = new StreamWriter(ReplacListBox.Text))
{
foreach(SerchReplacePair n in SerchReplacePairs)
{
// ファイルに書き込む
writer.WriteLine(n.SerchString + "\t" +n.ReplaceString);
}
}
}
TSVファイルからリスト・データを読み込む
Tsvファイルにデータを保存したら、Tsvファイルからデータを読み込む事ができるようにしておく必要があります。
Tsvファイルを直接テキストエディタなどで修正した際、区切り文字の入力を間違うと、必要な数の項目が取得できません。 SerchReplacePairsに、nullを登録しようとするとエラーが発生するので、取得した項目の数を確認し、2つ以下であれば、登録を行いません。
private void SelectButton_Click(object sender, RoutedEventArgs e)
{
//Tsvファイルから、リストデータを読み込む
using (StreamReader reader = new StreamReader(ReplacListBox.Text, Encoding.UTF8))
{
SerchReplacePairs.Clear();
while (!reader.EndOfStream) // ファイルの終末まで読み込む
{
string Line = reader.ReadLine(); // 1行ずつ読み込む
string[] items = Line.Split('\t'); // テキストを区切り文字で分割する
if (items.Length >= 2) // 要素数が2より小さい場合は、リストに登録しない
{
SerchReplacePairs.Add
(new SerchReplacePair()
{
SerchString = items[0],
ReplaceString = items[1]
});
}
}
}
}
UIデザイン
SerchReplacePair.cs
namespace SerchAndReplace03
{
class SerchReplacePair
{
public string SerchString { get; set; }
public string ReplaceString { get; set; }
}
}
MainWindow.xaml
<Window x:Class="SerchAndReplace03.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="400">
<DockPanel>
<DockPanel DockPanel.Dock="Top">
<Button Name="ListSaveButton"
Margin="0,5,5,0" Height="23" Width="60" DockPanel.Dock="Right" Click="ListSaveButton_Click">リスト保存</Button>
<Button Name="SelectButton"
Margin="5,5,5,0" Height="23" Width="60" DockPanel.Dock="Right" Click="SelectButton_Click">リスト読込</Button>
<TextBox Name="ReplacListBox"
Margin="5,5,0,0" Height="23" />
</DockPanel>
<DockPanel DockPanel.Dock="top">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Name="Add_SerchString"
Margin="5,5,0,0" Height="23" Grid.Column="0"/>
<TextBox Name="Add_ReplaceString"
Margin="5,5,5,0" Height="23" Grid.Column="1"/>
</Grid>
</DockPanel>
<DockPanel DockPanel.Dock="top">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="0,0,5,0">
<Button Name="AddButton"
Margin="5,5,0,0" Height="23" Width="50" Click="AddButton_Click"
>追加</Button>
<Button Name="EditButton"
Margin="5,5,0,0" Height="23" Width="50" Click="EditButton_Click"
>修正</Button>
<Button Name="DeleteButton"
Margin="5,5,0,0" Height="23" Width="50" Click="DeleteButton_Click"
>削除</Button>
</StackPanel>
</DockPanel>
<DockPanel DockPanel.Dock="Top">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center" Margin="0,5,0,0">
<ListView Name="ReplaceList"
SelectionChanged="ReplaceList_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn Header="検索文字列"
DisplayMemberBinding="{Binding SerchString}" />
<GridViewColumn Header="置換文字列"
DisplayMemberBinding="{Binding ReplaceString}" />
</GridView>
</ListView.View>
</ListView>
<StackPanel VerticalAlignment="Center" Margin="5,0,0,0">
<Button Name="upRow" Click="UpRow_Click">△</Button>
<Button Name="downRow" Margin="0,5,0,0" Click="DownRow_Click">▽</Button>
</StackPanel>
</StackPanel>
</DockPanel>
</DockPanel>
</Window>
MainWindow.xaml.cs
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace SerchAndReplace03
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
SetInitialList();
// パスとファイル名を設定
ReplacListBox.Text = @"H:\C#プロジェクト\ReplacePair.tsv";
}
ObservableCollection<SerchReplacePair> SerchReplacePairs = new ObservableCollection<SerchReplacePair>();
public void SetInitialList()
{
SerchReplacePairs.Add
(new SerchReplacePair()
{
SerchString = "検索",
ReplaceString = "置換"
});
SerchReplacePairs.Add
(new SerchReplacePair()
{
SerchString = "犬",
ReplaceString = "猫"
});
// ListViewのItemSourceに指定する
ReplaceList.ItemsSource = SerchReplacePairs;
}
private void ReplaceList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// 項目を選択したとき、それぞれのメンバを表示する
// ListViewで何も選択されていない場合は何もしない
if (ReplaceList.SelectedItem == null) return;
// ListViewで選択されている項目を取り出す
SerchReplacePair ListItem = (SerchReplacePair)ReplaceList.SelectedItem;
// ListViewで選択されている項目をテキストボックスに表示する
Add_SerchString.Text = ListItem.SerchString;
Add_ReplaceString.Text = ListItem.ReplaceString;
}
private void AddButton_Click(object sender, RoutedEventArgs e)
{
// Listの項目を追加
SerchReplacePairs.Add
(new SerchReplacePair()
{
SerchString = Add_SerchString.Text,
ReplaceString = Add_ReplaceString.Text
});
}
private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
// 選択した項目を削除
// listに項目が無い場合は何もしない
if (SerchReplacePairs.Count < 1) return;
// ListViewで選択されている項目を取り出す
SerchReplacePair item = (SerchReplacePair)ReplaceList.SelectedItem;
// listから選択された項目と一致するものを削除する
SerchReplacePairs.Remove(item);
// テキストボックスの内容をクリア
Add_SerchString.Text = null;
Add_ReplaceString.Text = null;
}
private void EditButton_Click(object sender, RoutedEventArgs e)
{
// 選択した項目を修正(選択した項目を変更する)
// ListViewで何も選択されていない場合は何もしない
if (ReplaceList.SelectedItem == null) return;
//選択されたアイテムのインディックスを取得する(挿入位置)
int itemIndex = ReplaceList.SelectedIndex;
// ListViewで選択されている項目を取り出す
SerchReplacePair item = (SerchReplacePair)ReplaceList.SelectedItem;
// listから選択された項目と一致するものを削除する
SerchReplacePairs.Remove(item);
// SerchReplacePairsに項目を挿入する
SerchReplacePairs.Insert
(itemIndex, new SerchReplacePair()
{
SerchString = Add_SerchString.Text,
ReplaceString = Add_ReplaceString.Text
});
}
private void UpRow_Click(object sender, RoutedEventArgs e)
{
// リストの項目を上に移動する
// ListViewで何も選択されていない場合は何もしない
if (ReplaceList.SelectedItem == null) return;
//選択されたアイテムのインディックスを取得する(挿入位置)
int itemIndex = ReplaceList.SelectedIndex;
// 項目が先頭の場合は何もしない
if (itemIndex == 0) return;
// ListViewで選択されている項目を取り出す
SerchReplacePair item = (SerchReplacePair)ReplaceList.SelectedItem;
// listから選択された項目と一致するものを削除する
SerchReplacePairs.Remove(item);
// SerchReplacePairsに項目を挿入する
SerchReplacePairs.Insert(itemIndex - 1, item);
}
private void DownRow_Click(object sender, RoutedEventArgs e)
{
// リストの項目を下に移動する
// ListViewで何も選択されていない場合は何もしない
if (ReplaceList.SelectedItem == null) return;
//選択されたアイテムのインディックスを取得する(挿入位置)
int itemIndex = ReplaceList.SelectedIndex;
// 項目が末尾の場合は何もしない
if (itemIndex == ReplaceList.Items.Count - 1) return;
// ListViewで選択されている項目を取り出す
SerchReplacePair item = (SerchReplacePair)ReplaceList.SelectedItem;
// listから選択された項目と一致するものを削除する
SerchReplacePairs.Remove(item);
// SerchReplacePairsに項目を挿入する
SerchReplacePairs.Insert(itemIndex + 1, item);
}
private void ListSaveButton_Click(object sender, RoutedEventArgs e)
{
// 置換リストを保存する
// 保存対象のリスト SerchReplacePairs
// using文を使ってファイルをクローズするコード
// ファイル名は、テキストボックスから取得する
using (StreamWriter writer = new StreamWriter(ReplacListBox.Text))
{
foreach (SerchReplacePair n in SerchReplacePairs)
{
// ファイルに書き込む
writer.WriteLine(n.SerchString + "\t" + n.ReplaceString);
}
}
}
private void SelectButton_Click(object sender, RoutedEventArgs e)
{
//Tsvファイルから、リストデータを読み込む
using (StreamReader reader = new StreamReader(ReplacListBox.Text, Encoding.UTF8))
{
SerchReplacePairs.Clear();
while (!reader.EndOfStream) // ファイルの終末まで読み込む
{
string Line = reader.ReadLine(); // 1行ずつ読み込む
string[] items = Line.Split('\t'); // テキストを区切り文字で分割する
if (items.Length >= 2) // 要素数が2より小さい場合は、リストに登録しない
{
SerchReplacePairs.Add
(new SerchReplacePair()
{
SerchString = items[0],
ReplaceString = items[1]
});
}
}
}
}
}
}