MediaImage类(型号)
public class MediaImage : INotifyPropertyChanged
{
public MediaImage(FileSystemInfo file)
{
this.Uri = new Uri(file.FullName);
this.Label = file.Name;
var getThumbnail = this.LoadThumbnail(this.Uri);
getThumbnail.ContinueWith(task =>
{
this.Thumbnail = task.Result;
});
}
public Uri Uri { get; }
public string Label { get; private set; }
private BitmapImage thumbnail;
public BitmapImage Thumbnail
{
get { return this.thumbnail; }
private set
{
this.thumbnail = value;
this.OnPropertyChanged();
}
}
private async Task<BitmapImage> LoadThumbnail(Uri uri)
{
return await Task.Run(() => this.GenerateThumbnail(uri));
}
private BitmapImage GenerateThumbnail(Uri uri)
{
var sourceBitmap = new BitmapImage();
sourceBitmap.BeginInit();
sourceBitmap.CacheOption = BitmapCacheOption.OnLoad;
sourceBitmap.DecodePixelWidth = 100;
sourceBitmap.UriSource = uri;
sourceBitmap.EndInit();
sourceBitmap.Freeze();
return sourceBitmap;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MainWindow C#
public partial class MainWindow
{
public MainWindow()
{
this.InitializeComponent();
}
private void OnLoadImagesClick(object sender, RoutedEventArgs e)
{
var dialog = new FolderBrowserDialog();
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
this.MediaImageView.LoadImages(dialog.SelectedPath);
}
}
}
ImageView XAML (界面)
<Grid>
<ListBox Style="{DynamicResource ImageViewListBoxStyle}"
ItemsSource="{Binding Images}"
ItemContainerStyle="{DynamicResource ImageViewListBoxItemStyle}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Panel.ZIndex="1000" Grid.Row="1" Text="{Binding Label}" Foreground="White" Width="100" Height="20" TextTrimming="CharacterEllipsis" VerticalAlignment="Center">
<TextBlock.Background>
<SolidColorBrush Opacity="0.50" Color="Black"/>
</TextBlock.Background>
</TextBlock>
<Image Grid.Row="0" Grid.RowSpan="2" Source="{Binding Thumbnail, UpdateSourceTrigger=PropertyChanged}" Width="100" Height="100"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
ImageView C#(接口代码)
public partial class ImageView
{
public ImageView()
{
this.InitializeComponent();
this.Images = new ObservableCollection<MediaImage>();
this.DataContext = this;
}
public ObservableCollection<MediaImage> Images { get; }
public void LoadImages(string path)
{
this.Images.Clear();
var option = SearchOption.TopDirectoryOnly;
var files = new DirectoryInfo(path).EnumerateFiles("*", option);
foreach (var file in files)
{
// Skip images already in our image collection
if (this.Images.Any(x => x.Uri.AbsolutePath == file.FullName))
{
continue;
}
this.Images.Add(new MediaImage(file));
}
}
}
问题行为的Gif
备注
通过研究和学习,我的理解是通过在我的XAML中将UpdateSourceTrigger
设置为PropertyChanged
,当异步任务完成且Thumbnail
属性触发时,每个Image都应更新它的绑定PropertyChanged
事件。
ListBox
中的每个图像都应该在异步任务完成时更新它的源代码(无论其他图像和任务如何)但似乎没有发生。在我当前的构建中,似乎所有图像在最后一个任务完成时都会更新。
问题
是否有一种简单的方法来修改我的代码,以便我的模型(MediaImage)异步更新某些属性,并且ListBox在任务完成时更新每个项目(最好通过PropertyChanged
事件)?
答案 0 :(得分:0)
我的解决方案简而言之:
首先,您必须将其可见性设置为false。 比你必须等待加载所有图像。 您可以使用FrameworkElement.Loaded事件(https://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.loaded(v=vs.110).aspx)。 最后,如果每个图像都已成功加载,请将其可见性设置为true。