C# 将CollectionViewSource与GroupDescriptions一起使用时,列表框滚动到视图中(即IsGrouping==True)
短版 更改选择时,我想将C# 将CollectionViewSource与GroupDescriptions一起使用时,列表框滚动到视图中(即IsGrouping==True),c#,wpf,C#,Wpf,短版 更改选择时,我想将列表框项目滚动到视图中 长版本 我有一个列表框,其中项资源绑定到一个集合视图源,其中组描述,如下例所示 代码隐藏文件中存在SelectionChanged事件 public List<Animal> Animals { get; set; } private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { ListBox control = (
列表框
项目滚动到视图中
长版本
我有一个列表框
,其中项资源
绑定到一个集合视图源
,其中组描述
,如下例所示
代码隐藏文件中存在SelectionChanged
事件
public List<Animal> Animals { get; set; }
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox control = (ListBox)sender;
control.ScrollIntoView(control.SelectedItem);
}
问题
始终返回ItemContainerGenerator.ContainerFromItem
,即使其状态表明所有容器都已生成李>null
我已经找到了解决我问题的办法。我确信我不是第一个碰到这个问题的人,所以我继续寻找StackOverflow的解决方案,我偶然发现了David的答案 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
SelectedItem
时,ItemContainerGenerator
总是返回null
?我相信是的。你应该看看Bea Stollnitz的博客。她有很多关于分组和虚拟化的好帖子:谢谢。我已经阅读了Bea Stollnitz关于WPF和CollectionViewSource和Grouping的几篇文章,我在问题中使用了她的分组示例。更新:我找到了一个解决方案,并将其作为答案发布。你应该将答案更改为正确答案,而不是上面的答案。@Valentin:我已经更改了标记的答案。然而,由于建议确实帮助我诊断了这个问题,如果您使用我的最终解决方案,最好将两个答案都投上一票。使用.NET 4.5.1和MVVM,您可以使用行为来实现这一点。该行为在这两种情况下都有效,因为它已经触发得很晚了。
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();
}