当单击的项目被重命名时,是什么使以下代码破坏了 a 的绑定 FileInformation
DataTemplate
?ListView
然后,如何正确通知FileInformation
已重命名的视图?
考虑一个包含 2 张图片、1.jpg 和 2.jpg 的文件夹。此文件夹由 Windows 10 1909 索引,UWP 应用为 1903 版。
用户选择文件夹后,我们创建FileInformationFactory
并检索VirtualizedFiles
对象并将其设置为CollectionViewSource
. 后者的视图填充了一个ICollectionView
绑定到 ListView 的 ItemsSource 的 OneWay。
我们在列表视图中显示每个文件Name
和. 重命名按钮采用 ListView.Selecteditem 并将其重命名为 1.jpg,并带有 .jpg 选项。FolderRelativeId
FileInformation
GenerateUniqueName
手头有两种方法。
1)给定代码最自然的一个是使用
FileInformation.RenameAsync()
,因为所选项目已经是FileInformation
。
2)从folder.GetFileAsync中获取Storagefile,其中name参数由FileInformation.Name给出,然后调用StorageFile.RenameAsync。
在这两种方法中,当我们重命名文件时,列表视图会按预期更新。但是,这不会持续很长时间,因为我一直在重命名,即使我给了重命名文件的时间。确实,在第一种情况下,我可以重命名文件,但是,当我不断重命名时,在某些不清楚的地方,列表视图似乎坚持以前重命名的名称并且与FolderRelativeId
. 例如,文件名显示为“1 (2).jpg”,而 FoldeRelativeId 以“1 (3).jpg.jpg”结尾。listview 无法将该项目识别为 ListView 的一部分,因为我无法再选择它并且重命名会引发捕获的异常。
这个问题在场景2中似乎没有出现,为什么?如何使用方案 1(即坚持FileInformation
重命名)并保持通知活动以更新 UI 而不会出现此错误?
另一个问题是如何在文件重命名后保持所选项目相同,因为经常(并非总是!)所选项目丢失(索引=-1),可能是因为 ICollectionview 已因来自通知的通知而被重置文件系统。
要查看错误,请取消注释 RenameButtonClick 事件中的行(并在上面几行注释来自 storagefile 的重命名调用)。
await fileInformation.RenameAsync("1.jpg", NameCollisionOption.GenerateUniqueName);
感谢任何帮助,因为我几天以来一直在这个问题上苦苦挣扎。谢谢
public sealed partial class Scenario5 : Page, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public Scenario5()
{
this.InitializeComponent();
}
private ICollectionView _fileCollectionView;
private StorageFolder _folder;
private QueryOptions _queryOptions;
private StorageFileQueryResult _query;
private FileInformationFactory _fileInformationFactory;
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)
{
return;
}
Information.Clear();
_folder = _pickedFolder;
_queryOptions = new QueryOptions
{
FolderDepth = FolderDepth.Deep,
IndexerOption = IndexerOption.UseIndexerWhenAvailable,
};
_query = _folder.CreateFileQueryWithOptions(_queryOptions);
_fileInformationFactory = new FileInformationFactory(_query, ThumbnailMode.SingleItem, 160,
ThumbnailOptions.UseCurrentScale, delayLoad: false);
var _vector = _fileInformationFactory.GetVirtualizedFilesVector();
CollectionViewSource.Source = _vector;
ItemCollectionView = CollectionViewSource.View;
}
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 ListView_ItemClick(object sender, ItemClickEventArgs e)
{
if (e.ClickedItem is FileInformation fileInformation)
{
Information.Add($"Click {fileInformation.Name}\n{fileInformation.FolderRelativeId}");
}
}
private async void RenameButton_Click(object sender, RoutedEventArgs e)
{
if (itemCollectionGridView.SelectedItem is FileInformation fileInformation)
{
Information.Add($"Selected item: {fileInformation.Name}\n{fileInformation.FolderRelativeId}");
try
{
var storageFile = await _folder.GetFileAsync(fileInformation.Name);
await storageFile.RenameAsync("1.jpg", NameCollisionOption.GenerateUniqueName);
Information.Add($"Renamed storagefile {storageFile.Name}\n{storageFile.FolderRelativeId}");
//await fileInformation.RenameAsync("1.jpg", NameCollisionOption.GenerateUniqueName);
Information.Add($"Renamed FileInformation result {fileInformation.Name}\n{fileInformation.FolderRelativeId}");
}
catch (Exception ex)
{
Information.Add($"{ex.Message}\n" +
$"{fileInformation.Name}\n{fileInformation.FolderRelativeId}");
}
}
}
private void ClearButton_Click(object sender, RoutedEventArgs e)
{
Information.Clear();
}
}
和 XAML
<Page
x:Class="Virtualization.Scenario5"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Virtualization"
xmlns:ba="using:Windows.Storage.BulkAccess"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
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="*"/>
<ColumnDefinition Width="48"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.ColumnSpan="1" Orientation="Horizontal"
BorderBrush="Blue" BorderThickness="0,0,2,2">
<AppBarButton Icon="Folder"
LabelPosition="Collapsed"
Click="FolderPickerButton_Click"/>
<AppBarButton Icon="Rename"
LabelPosition="Collapsed"
Click="RenameButton_Click"/>
<AppBarButton Icon="Clear"
LabelPosition="Collapsed" Label="Select Folder"
Click="ClearButton_Click"/>
</StackPanel>
<ListView x:Name="itemCollectionGridView" Grid.Row="1" Grid.Column="1"
ItemsSource="{x:Bind ItemCollectionView, Mode=OneWay}" IsItemClickEnabled="True"
ItemClick="ListView_ItemClick">
<ListView.ItemTemplate>
<DataTemplate x:DataType="ba:FileInformation">
<StackPanel MinHeight="100">
<TextBlock Text="{Binding Name}" TextWrapping="WrapWholeWords"/>
<TextBlock Text="{Binding Path}" TextWrapping="WrapWholeWords"/>
<TextBlock Text="{Binding FolderRelativeId}" TextWrapping="WrapWholeWords"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Grid.Row="1" Grid.Column="2" ItemsSource="{x:Bind Information, Mode=OneWay}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel ItemsUpdatingScrollMode="KeepLastItemInView" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>