过滤列表视图后的项目混乱

Posted

技术标签:

【中文标题】过滤列表视图后的项目混乱【英文标题】:Clutter of items after filtering the listview 【发布时间】:2021-10-22 13:02:53 【问题描述】:

我有一个带有 UserControl 作为 ItemTemplate 的 ListView。问题是在过滤和搜索项目之后,项目发生变化并且项目混淆了。例如,尚未下载的项目显示为已下载,已下载的项目显示为未下载。

问题是如何让每个项目单独工作而不影响其他项目?

这是我的列表视图

<ListView ItemsSource="x:Bind SubtitlesACV, Mode=OneWay">
                <ListView.ItemTemplate>
                    <DataTemplate x:DataType="model:SubsceneDownloadModel">
                        <usercontrol:SubsceneUserControl
                            Title="x:Bind Title"
                            Link="x:Bind Link"
                            SubtitleLanguage="x:Bind Language"
                            Translator="x:Bind Translator"/>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

这是我的用户控件

 <Grid>
        <SwipeControl x:Name="ListViewSwipeContainer">
            <Grid VerticalAlignment="Center">
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                </Grid.RowDefinitions>
                <TextBlock.../>

                <StackPanel
                    Grid.RowSpan="2"
                    HorizontalAlignment="Right"
                    VerticalAlignment="Center"
                    Orientation="Horizontal">
                    <AppBarButton
                        Name="OpenFolderButton"
                        MinWidth="75"
                        Margin="10,0,10,0"
                        Click="OpenFolderButton_Click"
                        Icon="OpenLocal"
                        IsTabStop="False"
                        Label="Open Folder"
                        Visibility="Collapsed"/>
                    <ProgressRing
                        Name="ProgressStatus"
                        Margin="10,0,10,0"
                        Visibility="Collapsed"/>
                    <AppBarButton
                        Name="DownloadHoverButton"
                        Margin="10,0,10,0"
                        Click="DownloadHoverButton_Click"
                        Icon="Download"
                        IsTabStop="False"
                        Label="Download"
                        Visibility="Collapsed"/>
                </StackPanel>

            </Grid>
        </SwipeControl>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="HoveringStates">
                <VisualState x:Name="HoverButtonsHidden"/>
                <VisualState x:Name="HoverButtonsShown">
                    <VisualState.Setters>
                        <Setter Target="DownloadHoverButton.Visibility" Value="Visible"/>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>

这是指针事件的代码

private void UserControl_PointerEntered(object sender, PointerRoutedEventArgs e)
        
            if (e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse ||
                e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Pen)
            
                VisualStateManager.GoToState(sender as Control, "HoverButtonsShown", true);
            
        

        private void UserControl_PointerExited(object sender, PointerRoutedEventArgs e)
        
            VisualStateManager.GoToState(sender as Control, "HoverButtonsHidden", true);
        

此代码用于通过 numberbox 和 AutoSuggestBox 进行过滤(其中 SubtitlesACV 是 AdvancedCollectionView)

SubtitlesACV.Filter = SubtitleFilter;

private bool SubtitleFilter(object subtitle)
        
            var query = subtitle as SubsceneDownloadModel;
            var selectedLanguage = cmbLanguage.SelectedItem as string;
            var selectedQuality = cmbQuaity.SelectedItem as string;
            if (string.IsNullOrEmpty(selectedQuality) || string.IsNullOrEmpty(selectedLanguage))
                return false;

            var name = query.Name ?? "";
            var translator = query.Translator ?? "";
            var comment = query.Comment ?? "";
            var language = query.Language ?? "";

            if (selectedLanguage.Equals(Consts.ALL_Language))
                selectedLanguage = "";
            
            if (selectedQuality.Equals(Consts.ALL_Qualities))
                selectedQuality = "";

            var episode = $"EnbEpisode.Value.ToString("00")";
            if (double.IsNaN(nbEpisode.Value) || nbEpisode.Value == 0)
                episode = "";

            return (name.Contains(selectedQuality, StringComparison.OrdinalIgnoreCase)
                    || translator.Contains(selectedQuality, StringComparison.OrdinalIgnoreCase)
                    || comment.Contains(selectedQuality, StringComparison.OrdinalIgnoreCase))
                    && language.Contains(selectedLanguage, StringComparison.OrdinalIgnoreCase)
                    && (name.Contains(AutoSuggest.Text, StringComparison.OrdinalIgnoreCase)
                    || translator.Contains(AutoSuggest.Text, StringComparison.OrdinalIgnoreCase)
                    || comment.Contains(AutoSuggest.Text, StringComparison.OrdinalIgnoreCase))
                    && (name.Contains(episode, StringComparison.OrdinalIgnoreCase)
                    || translator.Contains(episode, StringComparison.OrdinalIgnoreCase)
                    || comment.Contains(episode, StringComparison.OrdinalIgnoreCase));
        

首先,下载第 16 集并出现打开文件夹按钮。可以看出,第 17、18 和 19 集显示了下载按钮,这是绝对正确的。

enter image description here

现在如果我们用下面的代码过滤剧集号,一个尚未下载的项目会显示打开文件夹按钮这是错误的。

enter image description here

现在,如果我们从 AutoSuggestBox 搜索第 16 集(之前下载的),所有项目都将变为未下载模式。

enter image description here

【问题讨论】:

您能否尝试将 ListView 的默认 ItemsPanel 替换为 StackPanel,看看您是否仍然会遇到问题? @RoyLi-MSFT 感谢您使用 StackPanel 已修复,但 ItemsStackPanel 不起作用 @RoyLi-MSFT 我的问题已经解决了,但是现在我的 listview 性能急剧下降,滚动项目很慢,加载 listview 项目很慢......没有更好的方法吗? 【参考方案1】:

首先,你的行为原因是UI virtualization。这意味着代表项目的 UI 元素是按需创建的。面板有时会重用一些项目,这就是你得到这种行为的原因。目前,使用UI virtualization时没有很好的解决方法。

如果您没有大量数据,您可以只使用StackPanel,它不会启用UI virtualization。但是如果你有大量的数据,那么你需要自己优化性能。例如,将数据切割成不同的部分,一次只加载部分数据。在需要时加载数据的其他部分。这样,您就可以避免这种行为。

如果你有大量的数据,你仍然想使用UI virtualization,你可以做的是清除用户控件中的缓存数据。例如,在加载用户控件或将数据传递到用户控件时,清除该值并手动设置该值。但是你仍然不能完全避免这种行为。

【讨论】:

以上是关于过滤列表视图后的项目混乱的主要内容,如果未能解决你的问题,请参考以下文章

过滤器搜索后列表视图中的复选框更改位置

过滤后的jquery mobile listview计数项目

使用导致崩溃的搜索结果更新表视图

具有多个过滤器的 JQuery Mobile 可过滤列表视图

SAPUI5 列表绑定与 XML 视图中的过滤数据

将项目添加到列表视图并过滤现有项目