我有一个ListBox,直到最近它还在显示项目的平面列表。我能够使用myList.ItemContainerGenerator.ConainerFromItem(thing)检索列表中的ListBoxItem托管“东西”。
本周,我略微修改了ListBox,因为它绑定到的条目的CollectionViewSource启用了分组。现在,ListBox中的项被分组到漂亮的标题下。
然而,自从这样做后,ItemContainerGenerator.ContainerFromItem停止了工作-即使我知道ListBox中的项,它也会返回null。见鬼-即使ListBox填充了很多项,ContainerFromIndex(0)也会返回null!
如何从显示分组项的ListBoxItem中检索ListBox?
编辑:下面是一个精简示例的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>政务司司长:
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();
}
}发布于 2008-10-03 22:21:58
您可以使用让侦听ItemsGenerator.StatusChanged事件并对其做出反应,并等到生成ItemContainers后才能使用ContainerFromElement访问它们。
进一步搜索,我找到了某个有同样问题的人的a thread in the MSDN forum。这似乎是WPF中的一个错误,当一个人有一个GroupStyle设置。解决方案是在渲染过程之后平移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();
}发布于 2014-05-12 20:15:31
如果上面的代码不适用于您,请尝试以下代码
public class ListBoxExtenders : DependencyObject
{
public static readonly DependencyProperty AutoScrollToCurrentItemProperty = DependencyProperty.RegisterAttached("AutoScrollToCurrentItem", typeof(bool), typeof(ListBoxExtenders), new UIPropertyMetadata(default(bool), OnAutoScrollToCurrentItemChanged));
public static bool GetAutoScrollToCurrentItem(DependencyObject obj)
{
return (bool)obj.GetValue(AutoScrollToSelectedItemProperty);
}
public static void SetAutoScrollToCurrentItem(DependencyObject obj, bool value)
{
obj.SetValue(AutoScrollToSelectedItemProperty, value);
}
public static void OnAutoScrollToCurrentItemChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
{
var listBox = s as ListBox;
if (listBox != null)
{
var listBoxItems = listBox.Items;
if (listBoxItems != null)
{
var newValue = (bool)e.NewValue;
var autoScrollToCurrentItemWorker = new EventHandler((s1, e2) => OnAutoScrollToCurrentItem(listBox, listBox.Items.CurrentPosition));
if (newValue)
listBoxItems.CurrentChanged += autoScrollToCurrentItemWorker;
else
listBoxItems.CurrentChanged -= autoScrollToCurrentItemWorker;
}
}
}
public static void OnAutoScrollToCurrentItem(ListBox listBox, int index)
{
if (listBox != null && listBox.Items != null && listBox.Items.Count > index && index >= 0)
listBox.ScrollIntoView(listBox.Items[index]);
}
}XAML中的用法
<ListBox IsSynchronizedWithCurrentItem="True" extenders:ListBoxExtenders.AutoScrollToCurrentItem="True" ..../>发布于 2008-10-03 02:25:48
尝试从'thing‘开始向上解析VisualTree,直到到达ListBoxItem类型
https://stackoverflow.com/questions/165424
复制相似问题