【问题标题】:Scroll multiple listviews simultaneously C# UWP同时滚动多个列表视图 C# UWP
【发布时间】:2019-12-10 14:17:53
【问题描述】:

我正在使用 C# 构建一个 UWP 应用,但无法同时滚动多个列表视图。

我有 3 个列表视图:ListViewA、ListViewB 和 ListViewC。

如果我滚动 ListViewA,那么 ListViewB 和 ListViewC 都应该滚动。 如果我滚动 ListView B,则 ListViewA 和 ListViewC 将滚动,如果我滚动 ListViewC,也是如此。

我在 Stackoverflow 上完成了通常的搜索和尝试示例,以及其他成员提供的以下链接。仍然没有解决这个问题。希望这里的某个人能够提供一些启示,或提供一些关于在哪里寻找的见解?

我正在使用 MVVM 方法来填充列表视图,并且按预期运行。

现在只是让所有 3 个列表视图一次滚动。如果您需要任何其他信息,请告诉我。谢谢。

public class TestModel
{
    int ID {get; set;}
    string ColumnA {get; set;}
    string ColumnB {get; set;}
    string ColumnC {get; set;}  
}

public class MainPage : Page
{
        public TestModelViewModel ViewModel { get; set; }
        public MainPage()
        {
            this.InitializeComponent();
            ViewModel = new TestModelViewModel("Filename=TestModelDB.db");
        }
}

<ListView x:Name="ListViewA" ItemsSource="{x:Bind ViewModel.CollectionOfTestModelData, Mode=OneWay}">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="viewModels:TestModelViewModel" >
            <StackPanel>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="0" Text="{x:Bind ColumnA, Mode=OneWay}"/>
                </Grid>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

<ListView x:Name="ListViewB" ItemsSource="{x:Bind ViewModel.CollectionOfTestModelData, Mode=OneWay}">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="viewModels:TestModelViewModel" >
            <StackPanel>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="0" Text="{x:Bind ColumnB, Mode=OneWay}"/>
                </Grid>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

<ListView x:Name="ListViewC" ItemsSource="{x:Bind ViewModel.CollectionOfTestModelData, Mode=OneWay}">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="viewModels:TestModelViewModel" >
            <StackPanel>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="0" Text="{x:Bind ColumnC, Mode=OneWay}"/>
                </Grid>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

【问题讨论】:

    标签: c# listview uwp-xaml


    【解决方案1】:

    首先,可以订阅PointerEntered事件来判断哪个listView被滚动。下面我只以ListViewA和ListViewB为例。

    public bool ScrollViewerAScrolled = false;
    public bool ScrollViewerBScrolled = false;
    
    ListViewA.PointerEntered += ListViewA_PointerEntered;
    ListViewB.PointerEntered += ListViewB_PointerEntered;
    
    private void ListViewB_PointerEntered(object sender, PointerRoutedEventArgs e)
            {​
                ScrollViewerBScrolled = true;​
                ScrollViewerAScrolled = false;​
            }​
    
    
    private void ListViewA_PointerEntered(object sender, PointerRoutedEventArgs e)​
            {​
                ScrollViewerAScrolled = true;​
                ScrollViewerBScrolled = false;​
            }
    

    然后,可以通过VisualTreeHelper获取listView中的ScrollViewer(需要在ListView加载完成后调用)。 并订阅ViewChanged事件。例如,当ListViewA滚动时,会触发该事件,您可以在该事件中滑动ListViewB和ListViewC。同样适用于ListViewB和ListViewC。

    var scrollViewerA = FindVisualChild<ScrollViewer>(ListViewA, "ScrollViewer");
    var scrollViewerB = FindVisualChild<ScrollViewer>(ListViewB, "ScrollViewer");
    scrollViewerA.ViewChanged += (s, e) =>
                {​
                    if (ScrollViewerAScrolled)​  
                    {​
                        scrollViewerB.ChangeView(null, scrollViewerA.VerticalOffset, null, false);​
                    }
                 ​
                    ​
               };​
    
    scrollViewerB.ViewChanged += (s, e) =>​
                {​
        ​
                     if (ScrollViewerBScrolled)​
                     {​
                         scrollViewerA.ChangeView(null, scrollViewerB.VerticalOffset, null, false);​
                          ​
                     }​
    
                 };
    

    这里是如何在 ListView 中获取 ScrollViewr:

    protected T FindVisualChild<T>(DependencyObject obj, string name) where T : DependencyObject
                {
                    //get number
                    int count = VisualTreeHelper.GetChildrenCount(obj);
    
                    //Traversing each object based on the index
                    for (int i = 0; i < count; i++)
                    {
                        var child = VisualTreeHelper.GetChild(obj, i);
                        //According to the parameters to determine whether we are looking for the object
                        if (child is T && ((FrameworkElement)child).Name == name)
                        {
                            return (T)child;
                        }
                        else
                        {
                            var child1 = FindVisualChild<T>(child, name);
    
                            if (child1 != null)
                            {
                                return (T)child1;
                            }
    
    
                        }
                    }
    
                    return null;
    
                }
    

    【讨论】:

    • 感谢您的回复。我理解第一部分,第二部分我有点挣扎。您是在代码隐藏中创建新的 ScrollViewer 实例,还是在 Xaml 中创建新的 UI 元素?另外,您提到了 VisualTreeHelper,对它不太熟悉,但是 link 是否有一个很好的来源?
    • ListView 模板总是包含一个 ScrollViewer,所以我所做的是获取他的子对象“ScrollViewer”。VisualTreeHelper 用于遍历对象关系(沿子对象或父对象轴) .您可以使用它从父对象中获取特定的子对象。您显示的链接是正确的,我已经编辑了我的答案,您可以尝试一下。
    • 回复后,我做了一点研究,了解了如何在listview中访问ScrollViewer。我尝试实施我从该链接中学到的东西(顺便说一句,感谢您确认:) 以及您的解决方案并取得了一些令人敬畏的进展,但还没有完全实现。您的第二个回复很有意义,现在查看您的编辑,以便我更好地理解这个概念。整合更改后,我会告诉你进展如何。
    猜你喜欢
    • 2014-11-11
    • 1970-01-01
    • 2013-01-21
    • 2016-07-25
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多