加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – ListBox ScrollIntoView当使用GroupViewSource与GroupDesc

发布时间:2020-12-15 06:14:34 所属栏目:百科 来源:网络整理
导读:短版 当选择更改时,我想将ListBox项目滚动到视图中. 长版 我有一个ListBox,ItemsSource绑定到一个GroupViewSource与一个GroupDescription,如下面的例子. Window.Resources CollectionViewSource x:Key="AnimalsView" Source="{Binding Source={StaticResourc
短版

当选择更改时,我想将ListBox项目滚动到视图中.

长版

我有一个ListBox,ItemsSource绑定到一个GroupViewSource与一个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设置为当前不可见的项目,我希望它在视图中滚动.这是它变得棘手的地方,因为ListBox是组(IsGrouped属性为true),对ScrollIntoView的调用失败.

System.Windows.Controls.ListBox通过反射器.注意在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事件将永远不会触发.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读