Bell’s diary

WPFやC#の小ネタ、その他いろいろ気まぐれで投稿してみる予定。

WPFのListBoxで、自動で連番を割り振るConverter

ListBoxへの表示などで、単に画面上でだけ連番を振りたいことがあります。そんな時に簡単に使えるコンバーターです。
とりあえず、ItemsSourceから、ObservableCollectionやLivetのDispatcherCollectionなどへ直接バインドしている場合と、フィルターやソート処理を行うためにXAML上でCollectionViewSourceを定義してそれを挟んでバインドしている場合に対応しています。今のところそれ以外をItemsSourceとする需要がないのでそれ以外は未対応です。

まず、Converterの定義。

using System;
using System.Collections;
using System.Globalization;
using System.Windows.Data;

namespace Bells.Converters
{
    /// <summary>
    /// 連番を自動で振るコンバーター。
    /// 第一引数に連番を振る対象の要素、第二引数にそれを格納するコレクションを渡す
    /// </summary>
    class AutoEnumerator : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            var v = values[0];

            //直接コレクションなどにバインドしている場合
            var list = values[1] as IList;
            if (list!=null) return (list.IndexOf(v) + 1).ToString();

            //CollectionViewSourceをはさんでいる場合
            var view = values[1] as CollectionView;
            if(view!=null) return (view.IndexOf(v)+1).ToString();

            //それ以外は未対応
            throw new NotImplementedException();
        }
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}


次にこれを利用するXAML側。StaticResourceとして定義する部分は省略します。ListBox1の中からDataTemplateで定義されたTextBlockに連番を表示するものとして、

<TextBlock>
  <TextBlock.Text>
    <MultiBinding Converter="{StaticResource AutoEnumerator}" Mode="OneTime">
      <Binding/>
      <Binding Path="ItemsSource" ElementName="ListBox1"></Binding>
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>

こんな感じになります。やってることは単純で、ItemsSourceの中の1アイテムとItemsSourceそのものをConverterに渡して、その1アイテムのIndexを調べて、連番は1から始めるために+1して、さらにTextとして表示するためToString()してるだけです。

とりあえず第1回の小ネタとしてはこんなところで。