次のようなごく単純なViewModelクラスを用意します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
-
|
-
|
-
|
!
|
|
!
!
| using System;
using System.Collections.ObjectModel;
namespace Sample
{
public class SampleViewModel
{
public SampleViewModel()
{
this.Texts = Array.AsReadOnly(new[] { "萃香", "川内", "ラムザ", "弦巻マキ" });
}
public ReadOnlyCollection<string> Texts { get; private set; }
}
}
|
そしてこれを用いてメインウィンドウのXAMLを次のように書きます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| <Window
x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sample="clr-namespace:Sample"
Title="Sample"
SizeToContent="WidthAndHeight"
MinWidth="200">
<Window.DataContext>
<sample:SampleViewModel />
</Window.DataContext>
<StackPanel>
<ListBox ItemsSource="{Binding Texts}" />
</StackPanel>
</Window>
|
すると次のように表示されます。
ここで、各項目表示にインデックス値を使いたいなー、なんて思ったりすることがあります。
それを実現する方法としては次の2通りが考えられます。
- 各要素にインデックス値自体を持つリストデータをバインドする。
AlternationCount
プロパティと ItemsControl.AlternationIndex
添付プロパティを用いる。
前者が正攻法ですが、とにかくインデックスの表示さえできればいい場合にわざわざ元のリストデータをラップするというのは面倒です。(元のリストデータが ObservableCollection
だったりすると尚更)
後者はやや邪道ですが、ViewModelクラスに手を入れる必要はなく、XAMLの書き換えだけで済むという手軽さが魅力です。
具体的にはXAMLを次のように書き換えます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| <Window
x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sample="clr-namespace:Sample"
Title="Sample"
SizeToContent="WidthAndHeight"
MinWidth="200">
<Window.DataContext>
<sample:SampleViewModel />
</Window.DataContext>
<StackPanel>
<ListBox
ItemsSource="{Binding Texts}"
AlternationCount="{Binding Items.Count, RelativeSource={RelativeSource Self}}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ContentControl>
<Binding
Path="(ItemsControl.AlternationIndex)"
RelativeSource="{RelativeSource AncestorType=ListBoxItem}" />
</ContentControl>
<TextBlock Text=" : " />
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>
|
すると次のように表示されます。
AlternationCount
プロパティと ItemsControl.AlternationIndex
添付プロパティは、本来なら「1項目おきにスタイルを変更する」といった用途で利用されます。
しかし AlternationCount
プロパティの値を総項目数(即ち Items.Count
)と同じにしてしまえば、 ItemsControl.AlternationIndex
添付プロパティの値は項目のインデックスと等しくなります。
あとは DataTemplate
なり ControlTemplate
なりを用いて ItemsControl.AlternationIndex
添付プロパティ値をバインドして表示すればいいというわけです。
バインドする際、 RelativeSource
で ItemsControl.AlternationIndex
添付プロパティ設定対象のコントロール型(ListBox
なら ListBoxItem
)を参照するのを忘れずに。
XAMLはGUIを完全にテキストベースで書けるので楽しいですね。
フォームデザイナを使っていた頃はGUI作成なんて大嫌いでしたが、XAMLならいくらでも書こうという気になれます。