过滤列表视图后项目混乱
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。但你仍然无法完全避免这种行为。
我有一个带有 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。但你仍然无法完全避免这种行为。