UWP ListView 未加载项目
UWP ListView not loading items
我会用最简单的方式解释我的问题。
我一直在处理 listview 和 gridview 并绑定了很长时间,但现在我遇到了一个无法解释的问题,所以我真的需要一些帮助。
下面是我的列表视图的xaml代码。
<ListView Name="OtherVideosList" ItemsSource="{x:Bind VideoFiles}" SelectionChanged="OtherVideosList_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:VideoFile">
<StackPanel Orientation="Horizontal">
<Image Source="{x:Bind Thumbnail}"/>
<StackPanel>
<TextBlock Text="{x:Bind FileName}"/>
<TextBlock Text="{x:Bind Duration}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
我将它绑定到一个 ObservableCollection
下面是它的数据类型class。
public class VideoFile
{
public string FileName { get; set; }
public string Duration { get; set; }
public StorageFile File { get; set; }
public BitmapImage Thumbnail { get; set; }
}
使用这个 class 我正在创建项目来源
public ObservableCollection<VideoFile> VideoFiles { get; set; }
我使用一个按钮打开多个文件,然后将它们放入项目源,稍后在媒体元素上播放它们。下面是事件处理程序的代码。
private async void OpenClick(object sender, RoutedEventArgs e)
{
try
{
var p = new FileOpenPicker();
foreach (var item in videoTypes)
{
p.FileTypeFilter.Add(item);
}
//Curentplayingfiles is IReadOnlyList<StorageFiles>
CurrentlyPlayingFiles = await p.PickMultipleFilesAsync();
if (CurrentlyPlayingFiles.Count != 0)
{
if (CurrentlyPlayingFiles.Count == 1)
{ //this if block works absolutely fine
CurrentlyPlayingFile = CurrentlyPlayingFiles[0];
var s = await CurrentlyPlayingFile.OpenReadAsync();
ME.SetSource(s, CurrentlyPlayingFile.ContentType);
}
else
{
VideoFiles = new ObservableCollection<VideoFile>();
foreach (var file in CurrentlyPlayingFiles)
{
//Thumbnail and GetDuration are my own static methods to get thumbnail
//and duration property of the file respectively
VideoFiles.Add(new VideoFile { Thumbnail = await Thumbnail(file), Duration = await GetDuration(file), File = file, FileName = file.DisplayName });
}
//exception occurs on this very line below, because here OtherVideosList has zero items.
OtherVideosList.SelectedIndex = 0;
}
}
}
catch (Exception s){ var dr = s.Message; }
}
我在评论里给你提了要点
任何帮助将不胜感激,非常感谢..
在您的代码中您似乎绑定到一个可观察的视频文件集合。在添加项目之前不要将其设置为新的。如果集合已经绑定,这将打破你的绑定。改为清除列表中的所有项目
因此,您的页面未实现 InotifyPropertyChanged
,您可以通过两种方式修复它:
您可以在构造函数中初始化您的 VideoFiles
集合,一切都会正常进行。
另一种方式,实现INotifyPropertyChanged
接口。
顺便说一句,默认的x:Bind
模式是OneTime
所以在这一步你需要把Mode
改成OneWay
。
C#
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
private ObservableCollection<VideoFile> _videoFiles { get; set; }
public MainPage()
{
this.InitializeComponent();
}
public ObservableCollection<VideoFile> VideoFiles
{
get
{
return _videoFiles;
}
set
{
if (_videoFiles != value)
{
_videoFiles = value;
RaisePropertyChanged(nameof(VideoFiles));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OpenClick(object sender, RoutedEventArgs e)
{
VideoFiles = new ObservableCollection<VideoFile>();
VideoFiles.Add(new VideoFile()
{
Duration = "02:00",
FileName = "file name",
Thumbnail = new BitmapImage(new Uri("http://s.ill.in.ua/i/news/630x373/298/298656.jpg"))
});
}
private void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
XAML:
<ListView Name="OtherVideosList"
ItemsSource="{x:Bind VideoFiles, Mode=OneWay}">
您只监听 CollectionChanged
事件,而不是 VideoFiles
属性 本身的变化。试试这个:
// Assuming you're using C# 6. If not, assign it in constructor
public ObservableCollection<VideoFile> VideoFiles { get; set; } = new ObservableCollection<VideoFile>();
然后在else子句中:
else
{
VideoFiles.Clear();
foreach (var file in CurrentlyPlayingFiles)
{
//Thumbnail and GetDuration are my own static methods to get thumbnail
//and duration property of the file respectively
VideoFiles.Add(new VideoFile { Thumbnail = await Thumbnail(file), Duration = await GetDuration(file), File = file, FileName = file.DisplayName });
}
//exception occurs on this very line below, because here OtherVideosList has zero items.
OtherVideosList.SelectedIndex = 0;
}
当您将新集合分配给 VideoFiles
时,它会破坏绑定,您将不会再收到有关内容已更改的任何通知。
我会用最简单的方式解释我的问题。 我一直在处理 listview 和 gridview 并绑定了很长时间,但现在我遇到了一个无法解释的问题,所以我真的需要一些帮助。
下面是我的列表视图的xaml代码。
<ListView Name="OtherVideosList" ItemsSource="{x:Bind VideoFiles}" SelectionChanged="OtherVideosList_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:VideoFile">
<StackPanel Orientation="Horizontal">
<Image Source="{x:Bind Thumbnail}"/>
<StackPanel>
<TextBlock Text="{x:Bind FileName}"/>
<TextBlock Text="{x:Bind Duration}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
我将它绑定到一个 ObservableCollection 下面是它的数据类型class。
public class VideoFile
{
public string FileName { get; set; }
public string Duration { get; set; }
public StorageFile File { get; set; }
public BitmapImage Thumbnail { get; set; }
}
使用这个 class 我正在创建项目来源
public ObservableCollection<VideoFile> VideoFiles { get; set; }
我使用一个按钮打开多个文件,然后将它们放入项目源,稍后在媒体元素上播放它们。下面是事件处理程序的代码。
private async void OpenClick(object sender, RoutedEventArgs e)
{
try
{
var p = new FileOpenPicker();
foreach (var item in videoTypes)
{
p.FileTypeFilter.Add(item);
}
//Curentplayingfiles is IReadOnlyList<StorageFiles>
CurrentlyPlayingFiles = await p.PickMultipleFilesAsync();
if (CurrentlyPlayingFiles.Count != 0)
{
if (CurrentlyPlayingFiles.Count == 1)
{ //this if block works absolutely fine
CurrentlyPlayingFile = CurrentlyPlayingFiles[0];
var s = await CurrentlyPlayingFile.OpenReadAsync();
ME.SetSource(s, CurrentlyPlayingFile.ContentType);
}
else
{
VideoFiles = new ObservableCollection<VideoFile>();
foreach (var file in CurrentlyPlayingFiles)
{
//Thumbnail and GetDuration are my own static methods to get thumbnail
//and duration property of the file respectively
VideoFiles.Add(new VideoFile { Thumbnail = await Thumbnail(file), Duration = await GetDuration(file), File = file, FileName = file.DisplayName });
}
//exception occurs on this very line below, because here OtherVideosList has zero items.
OtherVideosList.SelectedIndex = 0;
}
}
}
catch (Exception s){ var dr = s.Message; }
}
我在评论里给你提了要点 任何帮助将不胜感激,非常感谢..
在您的代码中您似乎绑定到一个可观察的视频文件集合。在添加项目之前不要将其设置为新的。如果集合已经绑定,这将打破你的绑定。改为清除列表中的所有项目
因此,您的页面未实现 InotifyPropertyChanged
,您可以通过两种方式修复它:
您可以在构造函数中初始化您的
VideoFiles
集合,一切都会正常进行。另一种方式,实现
INotifyPropertyChanged
接口。 顺便说一句,默认的x:Bind
模式是OneTime
所以在这一步你需要把Mode
改成OneWay
。
C#
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
private ObservableCollection<VideoFile> _videoFiles { get; set; }
public MainPage()
{
this.InitializeComponent();
}
public ObservableCollection<VideoFile> VideoFiles
{
get
{
return _videoFiles;
}
set
{
if (_videoFiles != value)
{
_videoFiles = value;
RaisePropertyChanged(nameof(VideoFiles));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OpenClick(object sender, RoutedEventArgs e)
{
VideoFiles = new ObservableCollection<VideoFile>();
VideoFiles.Add(new VideoFile()
{
Duration = "02:00",
FileName = "file name",
Thumbnail = new BitmapImage(new Uri("http://s.ill.in.ua/i/news/630x373/298/298656.jpg"))
});
}
private void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
XAML:
<ListView Name="OtherVideosList"
ItemsSource="{x:Bind VideoFiles, Mode=OneWay}">
您只监听 CollectionChanged
事件,而不是 VideoFiles
属性 本身的变化。试试这个:
// Assuming you're using C# 6. If not, assign it in constructor
public ObservableCollection<VideoFile> VideoFiles { get; set; } = new ObservableCollection<VideoFile>();
然后在else子句中:
else
{
VideoFiles.Clear();
foreach (var file in CurrentlyPlayingFiles)
{
//Thumbnail and GetDuration are my own static methods to get thumbnail
//and duration property of the file respectively
VideoFiles.Add(new VideoFile { Thumbnail = await Thumbnail(file), Duration = await GetDuration(file), File = file, FileName = file.DisplayName });
}
//exception occurs on this very line below, because here OtherVideosList has zero items.
OtherVideosList.SelectedIndex = 0;
}
当您将新集合分配给 VideoFiles
时,它会破坏绑定,您将不会再收到有关内容已更改的任何通知。