过滤列表视图后项目混乱

Clutter of items after filtering the listview

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

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

这是我的 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 = $"E{nbEpisode.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

首先,你的行为的原因是UI virtualization。这意味着代表项目的 UI 个元素是按需创建的。面板有时会重复使用某些项目,这就是您出现此行为的原因。目前使用UI virtualization.

没有很好的办法解决这个问题

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

如果你有大量的数据,你仍然想使用UI virtualization,你可以做的是清除用户控件中的缓存数据。比如在加载usercontrol或者向usercontrol传递数据的时候,清除value,手动设置value。但你仍然无法完全避免这种行为。