ListBoxで各項目の間隔をあけて選択できない領域を作る




 ListBoxで各項目の間隔をあけて選択できない領域を作りたい(単純に項目の間隔をあけるだけでなく項目と項目の間をクリック/タップしてもSelectionChangedイベントが発生しないようにしたい)場合、2007年の投稿で紹介したListBoxItemのControlTemplateを変更して選択できる領域を限定する方法でも一見実現可能なように思えますが、この場合最後の項目の後にも間隔があいてしまうという問題があります。このような場合、カスタムのPanelを作成し、それをListBoxのItemsPanelTemplateとして設定する方法で実現することができます。


C#

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SkipPanelSample
{
    public class SkipPanel : Panel
    {
        public SkipPanel()
            : base()
        {
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            Size panelDesiredSize = new Size();

            foreach (UIElement child in Children)
            {
                child.Measure(availableSize);
                panelDesiredSize = child.DesiredSize;
            }

            return panelDesiredSize;
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            double y = 0;
            foreach (UIElement child in Children)
            {
                child.Arrange(new Rect(new Point(0, y), child.DesiredSize));
                y += child.DesiredSize.Height * 2;
            }
            return finalSize;
        }

    }
}



 このSkipPanelでは項目1つの高さ分間隔をあけて配置するようにしています。SilverlightWindows Phone OSではPanelクラスにInternalChildrenプロパティがないため通常のChildrenプロパティを使用していますが、WPFではMeasureCoreやArrangeCoreなどのオーバーライドの場合Panel.InternalChildren プロパティ (System.Windows.Controls)を使用することが推奨されています。


XAML

<ListBox ItemsSource="{Binding Collection}" FontSize="64">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="White" BorderThickness="2" Margin="5">
                <TextBlock Text="{Binding Property1}" Margin="10" Width="400"/>
            </Border>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <local:SkipPanel/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>