ItemContainerGenerator.ContainerFromItem如何与分组列表一起使用?
时间:2020-03-06 15:03:32 来源:igfitidea点击:
我有一个ListBox,直到最近才显示项目的平面列表。我能够使用myList.ItemContainerGenerator.ConainerFromItem(thing)检索在列表中托管"事物"的ListBoxItem。
本周,我对ListBox进行了一些修改,因为它为其项目绑定到的CollectionViewSource已启用分组。现在,ListBox中的项目被分组在漂亮的标题下面。
但是,由于这样做,ItemContainerGenerator.ContainerFromItem已停止工作,即使对于我知道在ListBox中的项目,它也返回null。即使ListBox填充了很多项目,Heck ContainerFromIndex(0)仍返回null!
如何从显示分组项目的列表框中检索ListBoxItem?
编辑:这是XAML,后面是精简示例的代码。这会引发NullReferenceException,因为即使列表中有四个项,ContainerFromIndex(1)也会返回null。
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(); } }
解决方案
尝试从"事物"中解析VisualTree,直到达到ListBoxItem类型
我们必须侦听并响应ItemsGenerator.StatusChanged
事件,并等待直到生成ItemContainers才能使用ContainerFromElement访问它们。
进一步搜索,我在MSDN论坛中发现了一个有相同问题的人的话题。当设置了GroupStyle时,这似乎是WPF中的一个错误。解决方案是在渲染过程之后平移对ItemGenerator的访问。下面是问题的代码。我试过了,它有效:
void ItemContainerGenerator_StatusChanged(object sender, EventArgs e) { if (listBox1.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated) { listBox1.ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged; Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Input, new Action(DelayedAction)); } } void DelayedAction() { var i = listBox1.ItemContainerGenerator.ContainerFromIndex(1) as ListBoxItem; // select and keyboard-focus the second item i.IsSelected = true; i.Focus(); }