MediaImage類(型號)異步加載的圖像的所有顯示在UI同時
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));
}
}
主窗口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設置UpdateSourceTrigger
至PropertyChanged
在我的XAML中,當異步任務完成並且Thumbnail
屬性觸發PropertyChanged
事件時,每個圖像應該更新它的綁定。
ListBox
中的每個圖像應該在異步任務完成時更新它的源代碼(不管其他圖像和任務),但似乎沒有發生。在我目前的版本中,當最後一項任務完成時,似乎所有圖像都會更新。
問題
有一種簡單的方法來修改我的代碼,使我的模型(MediaImage)異步更新某些屬性和它的任務完成(通過PropertyChanged
事件最好)列表框更新每個項目?
UpdateSourceTrigger對OneWay綁定沒有影響。它控制TwoWay或OneWayToSource何時更新綁定的Source屬性。並將其設置爲「PropertyChanged」與INotifyPropertyChanged接口的「PropertyChanged」事件無關。 – Clemens
嘗試將隨機延遲添加到'GenerateThumbnail'(通過'Thread.Sleep'),以便每個縮略圖生成需要不同的時間並查看會發生什麼。 – Evk
有關如何異步加載和顯示圖像的示例,您可能需要查看[此答案](http://stackoverflow.com/a/43124089/1136211)。 – Clemens