ぼやきごと/2015-02-25/WPF・XAML: ItemsControl の各項目表示にインデックス値を使う のバックアップの現在との差分(No.1)


  • 追加された行はこの色です。
  • 削除された行はこの色です。
#blog2navi()
*WPF・XAML: ItemsControl の各項目表示にインデックス値を使う [#b72e000a]

次のようなごく単純なViewModelクラスを用意します。

#code(csharp){{
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を次のように書きます。

#code(pre){{
<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>
}}

すると次のように表示されます。

#ref(サンプルウィンドウ表示1.png,left,nolink);
#ref(サンプルウィンドウ表示1.png,left,nolink,サンプルウィンドウ表示1);

ここで、各項目表示にインデックス値を使いたいなー、なんて思ったりすることがあります。~
それを実現する方法としては次の2通りが考えられます。

-各要素にインデックス値自体を持つリストデータをバインドする。
-@code{AlternationCount}; プロパティと @code{ItemsControl.AlternationIndex}; 添付プロパティを用いる。

前者が正攻法ですが、とにかくインデックスの表示さえできればいい場合にわざわざ元のリストデータをラップするというのは面倒です。(元のリストデータが @code{ObservableCollection}; だったりすると尚更)

後者はやや邪道ですが、ViewModelクラスに手を入れる必要はなく、XAMLの書き換えだけで済むという手軽さが魅力です。~
具体的にはXAMLを次のように書き換えます。

#code(pre){{{
<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>
}}}

すると次のように表示されます。

#ref(サンプルウィンドウ表示2.png,left,nolink);
#ref(サンプルウィンドウ表示2.png,left,nolink,サンプルウィンドウ表示2);

@code{AlternationCount}; プロパティと @code{ItemsControl.AlternationIndex}; 添付プロパティは、本来なら「1項目おきにスタイルを変更する」といった用途で利用されます。

-[[ItemsControl.AlternationCount プロパティ - MSDN>https://msdn.microsoft.com/ja-jp/library/system.windows.controls.itemscontrol.alternationcount.aspx]]
-[[ListBoxの色を一行置きに変える - Simple is best>http://blogs.yahoo.co.jp/elku_simple/25847797.html]]

しかし @code{AlternationCount}; プロパティの値を総項目数(即ち @code{Items.Count};)と同じにしてしまえば、 @code{ItemsControl.AlternationIndex}; 添付プロパティの値は項目のインデックスと等しくなります。~
あとは @code{DataTemplate}; なり @code{ControlTemplate}; なりを用いて @code{ItemsControl.AlternationIndex}; 添付プロパティ値をバインドして表示すればいいというわけです。~
バインドする際、 @code{RelativeSource}; で @code{ItemsControl.AlternationIndex}; 添付プロパティ設定対象のコントロール型(@code{ListBox}; なら @code{ListBoxItem};)を参照するのを忘れずに。

XAMLはGUIを完全にテキストベースで書けるので楽しいですね。~
フォームデザイナを使っていた頃はGUI作成なんて大嫌いでしたが、XAMLならいくらでも書こうという気になれます。

RIGHT:Category: &#x5b;[[C#>ぼやきごと/カテゴリ/C#]]&#x5d;&#x5b;[[WPF・XAML>ぼやきごと/カテゴリ/WPF・XAML]]&#x5d;&#x5b;[[プログラミング>ぼやきごと/カテゴリ/プログラミング]]&#x5d; - 2015-02-25 23:46:59
----
RIGHT:&blog2trackback();
#comment(above)
#blog2navi()