2012/02/03

ListView のソート

DisplayMemberBinding を使って表示させる方法なら前回の方法で大丈夫だったけど、CellTemplate の中でバインディングを指定する場合は何を参照して良いやらわからないことになるということが発覚。

まず思い浮かぶのが、俺版の GridViewColumnHeader を作るという方法。

public class SortableGridViewColumnHeader : GridViewColumnHeader
{
    static SortableGridViewColumnHeader()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(SortableGridViewColumnHeader),
            new FrameworkPropertyMetadata(typeof(GridViewColumnHeader)));
    }

    public SortableGridViewColumnHeader()
    {
        DefaultStyleKey = typeof(GridViewColumnHeader);
    }

    public static readonly DependencyProperty SortPathProperty =
        DependencyProperty.Register("SortPath", typeof(string), typeof(SortableGridViewColumnHeader));
    public string SortPath
    {
        get
        {
            return GetValue(SortPathProperty) as string;
        }
        set
        {
            SetValue(SortPathProperty, value);
        }
    }
}

これを使えば問題解決!と思ったのだけど、カラムのリサイズ時の(境界付近に持って行ったときの)カーソルが変わらなくなるという、よく分からない現象に遭遇したので没に。スタイル関連の問題なのだろうと思って、上のコードでもちょっといじってあるけど変化なかった。

で、俺版の x:Name みたいなのは作れないのかーと調べてたらそれっぽい機能があったので使ってみた。添付プロパティとかいう機能らしい。正確には DockPanel.Dock みたいなプロパティを実装するための仕組みらしい。

public class Sortable
{
    public static readonly DependencyProperty SortPathProperty =
        DependencyProperty.RegisterAttached("SortPath", typeof(string), typeof(Sortable));
    public static void SetSortPath(GridViewColumnHeader element, string value)
    {
        element.SetValue(SortPathProperty, value);
    }
    public static string GetSortPath(GridViewColumnHeader element)
    {
        return (string)element.GetValue(SortPathProperty);
    }
}

こうやっておいて、XAML には、

<GridViewColumn Width="120" CellTemplate="{StaticResource NameColumnTemplate}">
    <GridViewColumnHeader Content="なまえ" ore:Sortable.SortPath="Name" />
</GridViewColumn>
<GridViewColumn Width="80" CellTemplate="{StaticResource GenderColumnTemplate}">
    <GridViewColumnHeader Content="せいべつ" ore:Sortable.SortPath="Gender" />
</GridViewColumn>
<GridViewColumn Width="80" CellTemplate="{StaticResource RaceColumnTemplate}">
    <GridViewColumnHeader Content="しゅぞく" ore:Sortable.SortPath="Race" />
</GridViewColumn>

こんな感じに記述すれば、あとはクリック時のコードビハインドで、

var path = header.GetValue(Sortable.SortPathProperty) as string;

これで取得完了。動作も正常。

やったね!!!

0 件のコメント:

コメントを投稿