我正在使用 UWP 应用程序FileInformationFactory
检索文件对象的虚拟化向量,该向量被转换为FileInformation
并显示在GridView
.
我想查询插入笔记本电脑的 SD 卡上的文件夹并比较该文件夹的虚拟化情况GridView
当此文件夹位于FullyIndexed
位置,例如我的桌面。
该 SD 卡有一个包含 15,000 个零字节文本文件的文件夹。每个文件都有命名x.txt
其中 x 的范围是 1-15000(这可以通过单击下面代码中的“添加”按钮在您选择的文件夹中生成;在我的机器上需要一分钟左右的时间,但请记住只执行一次!)。
结果显示在GridView
我在其中显示每个文件的名称。
In a FullyIndexed
我可以上下滚动的位置GridView
非常快,即使使用垂直滚动条也非常快且不稳定,并且GridView
尽管会有几秒钟的延迟,但总是会设法显示每个文件的名称。
In a NotIndexed
在 SD 卡或外部硬盘等位置,当我缓慢滚动时 GridView 会显示项目,但当我上下滚动太快时,GridView 会很快失去对项目的跟踪,例如当我的触控板使用垂直滚动条时。等待没有帮助。该应用程序仍然响应,但没有任何显示。即使向上滚动到顶部,也仅显示第一个元素名称,唯一的选择是重新显示整体并平滑滚动。
我怎样才能解决这个问题NotIndexed
地点?我不想将文件一一检索到内存中,因为这会占用太多时间,而且对于真实照片来说,会很快耗尽用户的 RAM。因此使用GetVirtualizedFilesVector
.
我以为这将是 GridView 的虚拟化,但事实似乎并非如此,而且该应用程序可以很好地处理真实的 17k 照片,但只能在FullyIndexed
地点。
谢谢
<Page
x:Class="Virtualization.Scenario4"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ba="using:Windows.Storage.BulkAccess"
xmlns:local="using:Virtualization"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="48"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.ColumnSpan="1" Orientation="Horizontal"
BorderThickness="0,0,2,2">
<AppBarButton x:Name="FolderPickerButton" Icon="Folder"
LabelPosition="Collapsed" Label="Select Folder"
Click="FolderPickerButton_Click"/>
<AppBarButton Icon="ViewAll"
LabelPosition="Collapsed"
Click="ViewAllAppBarButton_Click"/>
<AppBarButton Icon="Add"
LabelPosition="Collapsed"
Click="AddFilesAppBarButton_Click"/>
<AppBarSeparator/>
</StackPanel>
<GridView Grid.Row="1" Grid.Column="1"
ItemsSource="{x:Bind ItemCollectionView, Mode=OneWay}" IsItemClickEnabled="True" ItemClick="GridView_ItemClick">
<GridView.ItemTemplate>
<DataTemplate x:DataType="ba:FileInformation">
<Grid>
<TextBlock MinWidth="80" Text="{Binding Name}" TextWrapping="WrapWholeWords"/>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<ListView Grid.Row="1" Grid.Column="2" ItemsSource="{x:Bind Information, Mode=OneWay}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
public sealed partial class Scenario4 : Page, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public Scenario4()
{
this.InitializeComponent();
}
private ICollectionView _fileCollectionView;
private StorageFolder _folder;
private IStorageQueryResultBase _query;
private FileInformationFactory _fileInformationFactory;
private object _vector;
public CollectionViewSource CollectionViewSource { get; set; } = new CollectionViewSource();
public ICollectionView ItemCollectionView
{
get { return _fileCollectionView; }
set
{
if (_fileCollectionView != value)
{
_fileCollectionView = value;
OnPropertyChanged(nameof(ItemCollectionView));
}
}
}
public ObservableCollection<string> Information { get; private set; } = new ObservableCollection<string>();
private async void FolderPickerButton_Click(object sender, RoutedEventArgs e)
{
var _pickedFolder = await PickFolderAsync();
if (_pickedFolder == null)
{
Information.Add("Choose a folder");
return;
}
Information.Add("Generate 15k files with the Add button if not done already, otherwise click the ViewAll button");
_folder = _pickedFolder;
}
private async void Query_ContentsChanged(IStorageQueryResultBase sender, object args)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
Information.Add($"Contents Changed {sender.Folder.Name} {args}");
});
}
private void View_VectorChanged(IObservableVector<object> sender, IVectorChangedEventArgs @event)
{
if (@event.CollectionChange == CollectionChange.Reset)
{
Information.Add($"Vector Changed {@event.CollectionChange} ItemCount: {sender.Count} Index: {@event.Index}");
}
}
private static async Task<StorageFolder> PickFolderAsync()
{
var folderPicker = new FolderPicker
{
SuggestedStartLocation = PickerLocationId.Desktop,
ViewMode = PickerViewMode.Thumbnail
};
folderPicker.FileTypeFilter.Add("*");
var _pickedFolder = await folderPicker.PickSingleFolderAsync();
return _pickedFolder;
}
private void GridView_ItemClick(object sender, ItemClickEventArgs e)
{
if (e.ClickedItem is FileInformation fileInformation)
{
Information.Add(fileInformation.Name);
}
else
{
if (e.ClickedItem == null)
{
Information.Add("Null");
}
else
{
Information.Add(e.ClickedItem.ToString());
}
}
}
private async void AddFilesAppBarButton_Click(object sender, RoutedEventArgs e)
{
for (int i = 1; i <= 15000; i++)
{
await _folder.CreateFileAsync(i + ".txt", CreationCollisionOption.ReplaceExisting);
if (i % 250 == 0)
{
Information.Add(i.ToString());
}
}
}
private async void ViewAllAppBarButton_Click(object sender, RoutedEventArgs e)
{
if (_folder == null)
{
Information.Add("Choose folder first");
return;
}
var state = await _folder.GetIndexedStateAsync();
var queryOptions = new QueryOptions { FolderDepth = FolderDepth.Deep, IndexerOption = IndexerOption.UseIndexerWhenAvailable };
Information.Add($"{_folder.Name} is {state} {queryOptions.IndexerOption}");
_query = _folder.CreateFileQueryWithOptions(queryOptions);
var st = Stopwatch.StartNew();
var numOfFiles = (await _query.GetItemCountAsync());
st.Stop();
Information.Add($"{state} {queryOptions.IndexerOption}. Found {numOfFiles} in {st.ElapsedMilliseconds / 1000.0}");
if (numOfFiles==0)
{
Information.Add("Generate files by clicking the Add button");
return;
}
_fileInformationFactory = new FileInformationFactory(_query, ThumbnailMode.SingleItem, Constants.Thumbnail_Size,
ThumbnailOptions.UseCurrentScale, delayLoad: false);
_vector = _fileInformationFactory.GetVirtualizedFilesVector();
CollectionViewSource.Source = _vector;
ItemCollectionView = CollectionViewSource.View;
_query.ContentsChanged += Query_ContentsChanged;
CollectionViewSource.View.VectorChanged += View_VectorChanged;
}
}
For Constants.Thumbnail_Size
,将其设置为例如100.
Addendum
该问题与外部硬盘驱动器无关。我在现代 Thinkpad X1 Yoga 3rd Gen 上创建了一个未索引的分区。该问题已重现。