• 解决WPF ListView(ListBox) 嵌套元素无法滚动的问题


    我需要实现一个类似QQ好友分组的数据展示,需要用到两个 ListView 嵌套,代码大致如下:

    <ListView
              ItemsSource="{Binding datas}"
        <ListView.ItemTemplate>
            <DataTemplate>
                <Expander>
                    <Expander.Header>
                        <TextBlock Text="{Binding name}"/>
                    </Expander.Header>
                    <Expander.Content>
                        <ListView
                                  ItemsSource="{Binding name}"
                                  >
                        </ListView>
                    </Expander.Content>
                </Expander>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    但当把数据绑定上去后,发现分组元素可以滚动,但分组内的元素无法滚动:
    problem1

    根据网上大家所说是因为 ListView 内本身就含有一个 ScrollViewer,当两个 ListView 嵌套时,鼠标滚轮事件首先被内层的 ListView 接收,而内层的 ListView 的滚动条在此时是被禁用的(至少看起来是这样的),此时当数据超出一定长度时显示出来的滚动条是外部 ListView 的,故当鼠标在内层 ListView 中滚动时,内层的元素无法滚动。

    自此解决思路自然是将内部滚轮事件拦截下来,标记为已处理,然后手动激发一个滚轮事件,并将这个事件冒泡至上层的 ListView 来进行处理,于是添加一个 PreviewMouseWheel 事件:

    <ListView
              ItemsSource="{Binding datas}"
        <ListView.ItemTemplate>
            <DataTemplate>
                <Expander>
                    <Expander.Header>
                        <TextBlock Text="{Binding name}"/>
                    </Expander.Header>
                    <Expander.Content>
                        <ListView
                                  PreviewMouseWheel="ListView_PreviewMouseWheel"
                                  ItemsSource="{Binding name}"
                                  >
                        </ListView>
                    </Expander.Content>
                </Expander>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    
    private void ListView_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (!e.Handled)
        {
            // ListView拦截鼠标滚轮事件
            e.Handled = true;
    
            // 激发一个鼠标滚轮事件,冒泡给外层ListView接收到
            var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
            eventArg.RoutedEvent = UIElement.MouseWheelEvent;
            eventArg.Source = sender;
            var parent = ((Control)sender).Parent as UIElement;
            parent.RaiseEvent(eventArg);
        }
    }
    

    此时虽然鼠标滚轮事件在内层也能工作了,但是却出现了新的问题:
    problem2

    此时滚轮滚动过的单位依然是外层元素的实际高度(外层元素所包含的所有内层 ListView 的高度)。

    这里我想到的方法是在外层 ListView 上嵌套一个 ScrollViewer ,并将外层 ListView 的鼠标滚轮事件冒泡给 ScrollViewer 来处理,这样外层 ScrollViewer 便能接收到最内层 ListView 的鼠标滚轮事件了:
    over
    大致代码如下:

    <ScrollViewer>
        <ListView
                  ItemsSource="{Binding datas}"
                  PreviewMouseWheel="ListView_PreviewMouseWheel"
                  >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Expander>
                        <Expander.Header>
                            <TextBlock Text="{Binding name}"/>
                        </Expander.Header>
                        <Expander.Content>
                            <ListView
                                      PreviewMouseWheel="ListView_PreviewMouseWheel"
                                      ItemsSource="{Binding name}"
                                      >
                            </ListView>
                        </Expander.Content>
                    </Expander>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ScrollViewer>
    
    private void ListView_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (!e.Handled)
        {
            // ListView拦截鼠标滚轮事件
            e.Handled = true;
    
            // 激发一个鼠标滚轮事件,冒泡给外层ListView接收到
            var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
            eventArg.RoutedEvent = UIElement.MouseWheelEvent;
            eventArg.Source = sender;
            var parent = ((Control)sender).Parent as UIElement;
            parent.RaiseEvent(eventArg);
        }
    }
    

    完整代码:Github

  • 相关阅读:
    Mesos 配置项解析
    1039. Course List for Student (25)
    Cts框架解析(12)-ITargetPreparer
    通过ulimit改善linux系统性能(摘自IBM)
    HDU 1080 DP
    C语言调用Lua函数
    创建MySQL从库
    C# Func&lt;&gt;托付
    SpringMVC入门
    VNC连接Ubuntu 16.04桌面灰色的问题解决
  • 原文地址:https://www.cnblogs.com/Jaywhen-xiang/p/14253621.html
Copyright © 2020-2023  润新知