WPFでリスト表示
WPFでかいてるアプリで、コンテンツをリスト表示をしたいなと思いまして、その勉強をしました。
その結果をメモ。
メモなので読んでくれる方は結構脳内補完したり調べたりしながら読んでいただかないといけなさそうですが、ご容赦ください。
■調べる内容
まずやりたいことをやれるようになるには何調べたら良いのかを考えるところから。
コンテンツをリスト表示したい
→コンテンツ自体は何とか取得するとして
→リスト表示はバインディングでいい感じにしたい
→バインディングが分からぬ
→でもそもそもリスト表示って、Control何使えばいいの。
■ListViewとListBox
まずListViewとListBoxがあるということで、それがどう違うのかということを調べてみた。
その結果。
ListView:データアイテムをリスト表示する
ListBox:選択可能なアイテムをリスト表示する
ListViewだと選択できないの? という疑問はありつつも、とりあえず選択可能なアイテムを表示したいのでListBoxを使うことにしました。
■テンプレート
ListBoxでバインディングする、と調べるとItemTemplateとかDataTemplateとかをの話が出てくる。
それを調べて書いたのが以下のような感じの内容。
○xaml
<UserControl x:Class="TwitterUI_mod1.ListViewTest" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="TestListViewIteクラスを定義しているnamespace" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <DataTemplate x:Key="TestDataTemplate" DataType="{x:Type local:TestListViewItem}"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Name}"/> <TextBlock Text="{Binding Value}" /> <TextBlock Text="{Binding Id}"/> </StackPanel> </DataTemplate> <ListBox x:Name="TestListView" HorizontalAlignment="Left" ItemTemplate="{StaticResource TestDataTemplate}"/>
○cs
public class TestListViewItem { public string Name{ get; set;} public string Value{ get; set;} public int Id{ get; set;} }
正直良くわからず書いたんだけど、
・「ItemTemplate="{StaticResource TestDataTemplate}"」の部分で、このListBoxのItem一個一個はTestDataTemplateに従って表示するということを定義。
・DataTemplateのところで、このテンプレートの名前はTestDataTemplateで、元ネタはTestListViewItemであることを定義。
・Name、Value、IdをそれぞれTextBlockで表示することを定義
ということを書いている様子。xamlのほうで。
csのほうではテンプレートでつかっているTestListViewItemのクラスを定義。
■バインディング
ここまで書いて、やっとバインディング自体をよく分かっていないなということに気づいてそれを調べることに。
調べた結果は以下の記事。
第5回 WPFの「データ・バインディング」を理解する (1/3):連載:WPF入門 - @IT
新たにこれ見ながら書き起こすよりこれ読んでもらったほうが早い。
■最終的に。
全文書き写しではないけど、ピックアップすると以下のような感じになりました。
xamlは前述の通りでcsだけちょっと変えた。
public class TestListViewItem { public string Name{ get; set;} public string Value{ get; set;} public int Id{ get; set;} public TestListViewItem(string str1, string str2, int int1) { this.Name = str1; this.Value = str2; this.Id = int1; } } public ObservableCollection<TestListViewItem> TargetListItem = new ObservableCollection<TestListViewItem>(); public partial class ListViewTest : UserControl { public ListViewTest() { InitializeComponent(); TestListView.DataContext = TargetListItem; } private void Button_Click(object sender, RoutedEventArgs e) { int id = 0; int.TryParse(IdText.Text, out id); TestListView.Items.Add(new TestListViewItem(NameText.Text, ValueText.Text, id)); } }
UIのほうにTextBoxを3つ用意しておいてそれぞれNameText、ValueText、IdTextと名付けておく。
それで、ボタンが押されるとその文字列をリスト表示に追加する、という仕掛けにしてみた。
TestListView.DataContext = TargetListItem;
この部分が美しくない気がしているんだけど、とりあえず動いたのでこれで良いかということにした。
正直、=が参照渡しだからよかったものの、これがclone作って渡すようなものだったら動いてないし、その定義はどこ見たら安心できるのか分かってないので、偶然動いてるというレベルではある。
でも、趣味で書いてるコードだし、完成品を外に出すつもりも今のところ無い(自分で使うだけだ)し、動いているならこれで良いことにした。
これ以外にもまだまだ書かなきゃいけないコードあるし。
今日はここまででした。
※追記。
ObservableCollectionを使っているのはどこかでこれ使うべき、みたいな話読んだのでそれに従っただけなんだけど、既に参考にしたソースコードの状況からは離れているので使うべきなのかそうじゃないのかよく分からず。
ObservableCollectionを使っていることに気づいたのがこの記事書きながらなので、調べ直す元気もなく。
テスト実装じゃなくて、本実装のときには調べてみるつもり。