WPFのListViewは、Grid表示ができます。そのため、多項目の配列のデータを表示する際に利用できます。
ListViewコントロールは、List型のデータを格納できますが、Grid表示をする場合は、データソースを指定して利用する場合がほとんどです。そのため、項目の追加や削除は、データソースに指定するリストに対して操作を行う必要があります。
具体的には、データを格納するクラスのメソッドとして、データに対して行いたい操作を用意するのが良いかもしれません。もちろん、データ上はそのままで、View上でのみソート順序を変更したり、表示、非表示する場合は、データを表示するクラスのメソッドにしたほうがよいと思います。
プログラムの動作
テキストボックスに値を入れて、Add Itemボタンを押すと、ListViewに項目が追加されます。ListViewの項目を選択すると、テキストボックスに項目の内容が表示されます。項目を選択して、Delete Itemボタンを押すと項目が削除されます。
データを格納するクラスを作成する
まずは、データを格納するクラスを作成します。
public class User
{
public string Name { get; set; }
public int Age { get; set; }
public string Mail { get; set; }
}
データを格納するクラスのList型のコンテナを作成を作成する
次に、データを格納するクラスのList型のコンテナを作成します。
データを格納するクラスでは、1つのデータ・セットだけを格納します。複数のデータ・セットを扱うには、複数のインスタンスを作成する必要があります。同じクラスの複数のインスタンスを簡単に扱うためのコンテナが、List型のコンテナです。
ここで、重要なポイントは、コントロールで表示するデータを格納するList型のコンテナには、Listクラスではなく、INotifyCollectionChangedインターフェースを持つ ObservableCollectionクラスを使用することです。
データソースを使って、ListBoxやListViewコントロールに、項目を表示する際、データソースが変更した際、コントロールに表示した内容も変更する必要があります。WPFでは、データソースが変更されたことをINotifyCollectionChangedインターフェースを使ってコントロールに伝える仕組みを使っています。そのため、INotifyCollectionChangedインターフェースを持っていない、Listクラスを使うと、データソースが変更されたことが、コントロールに伝わりません。その結果、データソースを更新してもUIの表示が更新されません。
INotifyCollectionChangedインターフェースを持つListクラスを自分で作ってもよいのですが、 INotifyCollectionChangedインターフェースを持つList型のコンテナとして、ObservableCollectionクラスが、用意されているので、特別な理由がなければ、そのまま使うことをおすすめします。
System.Collections.ObjectModel.ObservableCollection<User> items = new System.Collections.ObjectModel.ObservableCollection<User>();
List型のコンテナにデータ・セットを追加する
List型のコンテナのObservableCollectionクラスのインスタンスを作成したので、データ・セットを追加します。最後にListViewコントールlvUserのデータ・セットに指定します。
private void InitialItemAdd()
{
// 起動時にListViewに追加するItem;
items.Add
(new User()
{
Name = "John Doe",
Age = 42,
Mail = "john@doe-family.com"
}
);
items.Add
(new User()
{
Name = "Jane Doe",
Age = 39,
Mail = "jane@doe-family.com"
}
);
items.Add
(new User()
{
Name = "Sammy Doe",
Age = 7,
Mail = "sammy.doe@gmail.com"
}
);
// ListViewのItemSourceに指定する
lvUsers.ItemsSource = items;
}
選択したListViewの項目の内容を取得する
ListViewのSelectionChangedイベントを使用します。
private void LvUsers_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// 項目を選択したとき、それぞれのメンバを表示する
// ListViewで何も選択されていない場合は何もしない
if (lvUsers.SelectedItem == null) return;
// ListViewで選択されている項目を取り出す
User item = (User)lvUsers.SelectedItem;
}
int型のデータをstring型に変更する
今回は、データを格納するクラスを作りました。このクラスでは、明示的に、ToStringメソッドを実装していないため、int型をString型に変更するために、ToStringメソッドは使えません。
その場合、Convertクラスを使って、int型をsiring型に変換します。
textBox_Age.Text = Convert.ToString(item.Age);
プログラム実行時に項目を追加する
プログラム実行時に、項目を追加します。
値を格納しているList型コンテナに、項目を追加します。データソースを参照する設定をしているので、コンテナの内容が変更されると自動的に、ListViewの内容が更新されます。
string型のデータをint型に変更する
UIから、データソースに指定したデータに、新しい項目を追加する場合、Parseメソッドも使えますが、Parseを例外処理を実装する必要があります。そのため、例外処理を実装する必要がないTryParseメソッドを使用します。
private void Button1_Click(object sender, RoutedEventArgs e)
{
// textBox_Age.Textをintに変換する
int myAge;
if (int.TryParse("123", out myAge))
{
items.Add(new User()
{
Name = textBox_Name.Text,
Age = int.Parse(textBox_Age.Text),
Mail = textBox_Mail.Text
}
);
}
else
{
MessageBox.Show("Ageの値を数値に変換できません");
}
}
選択した項目を削除する
選択したアイテムを削除するためには、LitView.SelectedItemプロパティで選択されたアイテムを取り出して、Remove()メソッドでそのアイテムに一致するものをコレクションから削除します。
Remove()メソッドは引数に一致する最初のアイテムをコレクション構造になっている場合は、それに対応する処理が必要です。
選択した項目の内容が、テキストボックスに表示されるので、テキストボックスの内容を削除します。
private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
// 選択した項目を削除
// listに項目が無い場合は何もしない
if (items.Count < 1) return;
// ListViewで選択されている項目を取り出す
User item = (User)lvUsers.SelectedItem;
// listから選択された項目と一致するものを削除する
items.Remove(item);
// テキストボックスの内容をクリア
textBox_Name.Text = null;
textBox_Age.Text = null;
textBox_Mail.Text = null;
}
全体のコード
xaml
<Window x:Class="GridView02.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">
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBox Name="textBox_Name"
Margin="5,5,0,0" Height="23" Width="120"/>
<TextBox Name="textBox_Age"
Margin="5,5,0,0" Height="23" Width="50"/>
<TextBox Name="textBox_Mail"
Margin="5,5,0,0" Height="23" Width="200"/>
</StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="0,0,5,0">
<Button Name="button1"
Margin="5,5,0,0" Height="23" Width="75"
Click="Button1_Click"> Add Item </Button>
<Button Name="DeleteButton"
Margin="5,5,0,0" Height="23" Width="75"
Click="DeleteButton_Click" >Delete Item</Button>
</StackPanel>
<ListView Margin="10" Name="lvUsers" SelectionChanged="LvUsers_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn Header="Name"
Width="120"
DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Age"
Width="50"
DisplayMemberBinding="{Binding Age}" />
<GridViewColumn Header="Mail"
Width="150"
DisplayMemberBinding="{Binding Mail}" />
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</Window>
xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
namespace GridView02
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InitialItemAdd();
}
public class User
{
public string Name { get; set; }
public int Age { get; set; }
public string Mail { get; set; }
}
System.Collections.ObjectModel.ObservableCollection<User> items = new System.Collections.ObjectModel.ObservableCollection<User>();
private void InitialItemAdd()
{
// 起動時にListViewに追加するItem;
items.Add
(new User()
{
Name = "John Doe",
Age = 42,
Mail = "john@doe-family.com"
}
);
items.Add
(new User()
{
Name = "Jane Doe",
Age = 39,
Mail = "jane@doe-family.com"
}
);
items.Add
(new User()
{
Name = "Sammy Doe",
Age = 7,
Mail = "sammy.doe@gmail.com"
}
);
// ListViewのItemSourceに指定する
lvUsers.ItemsSource = items;
}
private void LvUsers_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// 項目を選択したとき、それぞれのメンバを表示する
// ListViewで何も選択されていない場合は何もしない
if (lvUsers.SelectedItem == null) return;
// ListViewで選択されている項目を取り出す
User item = (User)lvUsers.SelectedItem;
// ListViewで選択されている項目をテキストボックスに表示する
textBox_Name.Text = item.Name;
textBox_Age.Text = Convert.ToString(item.Age);
textBox_Mail.Text = item.Mail;
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
// 項目を追加する
// textBox_Age.Textをintに変換する
int myAge;
if (int.TryParse("123", out myAge))
{
items.Add(new User()
{
Name = textBox_Name.Text,
Age = int.Parse(textBox_Age.Text),
Mail = textBox_Mail.Text
}
);
}
else
{
MessageBox.Show("Ageの値を数値に変換できません");
}
}
private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
// 選択した項目を削除
// listに項目が無い場合は何もしない
if (items.Count < 1) return;
// ListViewで選択されている項目を取り出す
User item = (User)lvUsers.SelectedItem;
// listから選択された項目と一致するものを削除する
items.Remove(item);
// テキストボックスの内容をクリア
textBox_Name.Text = null;
textBox_Age.Text = null;
textBox_Mail.Text = null;
}
}
}
総括
参考サイト「C#のListViewを使ってみた」の内容ほぼそのままですが、C# WPFのListViewの基本的な使い方を確認することができました。
ListViewは、List型や配列型を扱うプログラムを作成する際、その動作や内容を確認する際にとても便利です。List型や配列型のデータを作成、編集するUIを持つプログラムを作成する際、活用できれば、より使いやすいプログラムが作成できそうです。