- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
精简版
我想在更改选择时将 ListBox
项目滚动到 View 中。
长版
我有一个 ListBox
,其 ItemsSource
绑定(bind)到一个 CollectionViewSource
和一个 GroupDescription
,如示例所示以下。
<Window.Resources>
<CollectionViewSource x:Key="AnimalsView" Source="{Binding Source={StaticResource Animals}, Path=AnimalList}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Category"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<ListBox x:Name="AnimalsListBox"ItemsSource="{Binding Source={StaticResource AnimalsView}}" ItemTemplate="{StaticResource AnimalTemplate}" SelectionChanged="ListBox_SelectionChanged">
<ListBox.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource CategoryTemplate}" />
</ListBox.GroupStyle>
</ListBox>
代码隐藏文件中有一个 SelectionChanged
事件。
public List<Animal> Animals { get; set; }
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox control = (ListBox)sender;
control.ScrollIntoView(control.SelectedItem);
}
现在。如果我将 AnimalsListBox.SelectedItem
设置为当前不可见的项目,我希望它在 View 中滚动。这是它变得棘手的地方,因为 ListBox
正在分组(IsGrouped
属性为 true
)调用 ScrollIntoView
失败。
System.Windows.Controls.ListBox
通过 Reflector。请注意 OnBringItemIntoView
中的 base.IsGrouping
。
public void ScrollIntoView(object item)
{
if (base.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
this.OnBringItemIntoView(item);
}
else
{
base.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(this.OnBringItemIntoView), item);
}
}
private object OnBringItemIntoView(object arg)
{
FrameworkElement element = base.ItemContainerGenerator.ContainerFromItem(arg) as FrameworkElement;
if (element != null)
{
element.BringIntoView();
}
else if (!base.IsGrouping && base.Items.Contains(arg))
{
VirtualizingPanel itemsHost = base.ItemsHost as VirtualizingPanel;
if (itemsHost != null)
{
itemsHost.BringIndexIntoView(base.Items.IndexOf(arg));
}
}
return null;
}
问题
ItemContainerGenerator.ContainerFromItem
始终返回 null
,即使它的状态表明所有容器都已生成。 最佳答案
我找到了解决问题的方法。我确信我不是第一个遇到这个问题的人,所以我继续在 StackOverflow 上搜索解决方案,我偶然发现了 David 的这个答案 about how ItemContainerGenerator works with a grouped list .
David 的解决方案是延迟访问 ItemContainerGenerator
,直到呈现过程之后。
我已经实现了这个解决方案,我将在后面详细介绍一些更改。
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox control = (ListBox)sender;
if (control.IsGrouping)
{
if (control.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(DelayedBringIntoView));
else
control.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
}
else
control.ScrollIntoView(control.SelectedItem);
}
private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
if (ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
return;
ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged;
Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(DelayedBringIntoView));
}
private void DelayedBringIntoView()
{
var item = ItemContainerGenerator.ContainerFromItem(SelectedItem) as ListBoxItem;
if (item != null)
item.BringIntoView();
}
变化:
IsGrouping
为 true
时才使用 ItemContainerGenerator
方法,否则继续使用默认的 ScrollIntoView
。 ItemContainerGenerator
是否就绪,如果是则调度操作,否则监听 ItemContainerGenerator
状态是否改变。这很重要,因为它就绪了StatusChanged
事件永远不会触发。 关于c# - 将 CollectionViewSource 与 GroupDescriptions 一起使用时的 ListBox ScrollIntoView(即 IsGrouping == True),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7366961/
精简版 我想在更改选择时将 ListBox 项目滚动到 View 中。 长版 我有一个 ListBox,其 ItemsSource 绑定(bind)到一个 CollectionViewSource 和
我是一名优秀的程序员,十分优秀!