かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

ListView(ListBoxも)で単一選択モードのときに項目を追加したときの挙動を変えたい

ListViewのSelectionModeをSingleにした状態で、先頭に要素を追加したりすると、勝手に選択項目にスクロールしてしまいます。

場合によっては嬉しいのかもしれないですが余計な動作と感じることもあるので、OFFにしたい…!と思って調べたら、そういうプロパティがみつかりませんでした。

実現方法

複数選択できるMultipleだと、選択項目があっても勝手にそこへスクロールしません。なので、SelectionChangedイベントで単一選択になるように制御してやります。なので、こんなビヘイビアを作っておいて、ぽとっとすれば完了ですね。

using Microsoft.Xaml.Interactivity;
using System;
using System.Diagnostics;
using System.Linq;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace App6
{
    [TypeConstraint(typeof(ListView))]
    public class SingleSelectBehavior : DependencyObject, IBehavior
    {
        private ListView AssociatedObject { get; set; }

        DependencyObject IBehavior.AssociatedObject
        {
            get { return this.AssociatedObject; }
        }

        public void Attach(DependencyObject associatedObject)
        {
            var lv = associatedObject as ListView;
            if (lv == null)
            {
                throw new InvalidOperationException();
            }

            this.AssociatedObject = lv;
            this.AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
        }

        private void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // 何か選択されたら
            if (e.AddedItems.Any())
            {
                // とりあえず1つだけ選択状態にする
                this.AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
                this.AssociatedObject.SelectedItems.Clear();
                this.AssociatedObject.SelectedItems.Add(e.AddedItems.First());
                this.AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
            }
        }

        public void Detach()
        {
            this.AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
        }
    }
}