最近までアイテムのフラットリストを表示していた ListBox があります。myList.ItemContainerGenerator.ConainerFromItem(thing) を使用して、リスト内の「もの」をホストする ListBoxItem を取得できました。
今週は ListBox を少し変更し、アイテムのバインド先の CollectionViewSource でグループ化が有効になっているようにしました。ListBox 内の項目が適切なヘッダーの下にグループ化されます。
ただし、これを行ってから、ItemContainerGenerator.ContainerFromItem は機能しなくなりました。ListBox にあることがわかっているアイテムに対しても null を返します。Heck - ContainerFromIndex(0) は、ListBox に多くの項目が入力されている場合でも null を返します!
グループ化された項目を表示している ListBox から ListBoxItem を取得するにはどうすればよいですか?
編集: これは、縮小された例の XAML とコード ビハインドです。これは、リストに 4 つの項目があるにもかかわらず、ContainerFromIndex(1) が null を返すため、NullReferenceException を発生させます。
XAML:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
Title="Window1">
<Window.Resources>
<XmlDataProvider x:Key="myTasks" XPath="Tasks/Task">
<x:XData>
<Tasks xmlns="">
<Task Name="Groceries" Type="Home"/>
<Task Name="Cleaning" Type="Home"/>
<Task Name="Coding" Type="Work"/>
<Task Name="Meetings" Type="Work"/>
</Tasks>
</x:XData>
</XmlDataProvider>
<CollectionViewSource x:Key="mySortedTasks" Source="{StaticResource myTasks}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="@Type" />
<scm:SortDescription PropertyName="@Name" />
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="@Type" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<ListBox
x:Name="listBox1"
ItemsSource="{Binding Source={StaticResource mySortedTasks}}"
DisplayMemberPath="@Name"
>
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
</ListBox>
</Window>
CS:
public Window1()
{
InitializeComponent();
listBox1.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
}
void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
if (listBox1.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
{
listBox1.ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged;
var i = listBox1.ItemContainerGenerator.ContainerFromIndex(1) as ListBoxItem;
// select and keyboard-focus the second item
i.IsSelected = true;
i.Focus();
}
}