2017-04-05 66 views
1

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)); 
     } 
    } 
} 

問題行爲

enter image description here

注意

通過研究和學習,這是我的理解是,通過的Gif設置UpdateSourceTriggerPropertyChanged在我的XAML中,當異步任務完成並且Thumbnail屬性觸發PropertyChanged事件時,每個圖像應該更新它的綁定。

ListBox中的每個圖像應該在異步任務完成時更新它的源代碼(不管其他圖像和任務),但似乎沒有發生。在我目前的版本中,當最後一項任務完成時,似乎所有圖像都會更新。

問題

有一種簡單的方法來修改我的代碼,使我的模型(MediaImage)異步更新某些屬性和它的任務完成(通過PropertyChanged事件最好)列表框更新每個項目?

+2

UpdateSourceTrigger對OneWay綁定沒有影響。它控制TwoWay或OneWayToSource何時更新綁定的Source屬性。並將其設置爲「PropertyChanged」與INotifyPropertyChanged接口的「PropertyChanged」事件無關。 – Clemens

+1

嘗試將隨機延遲添加到'GenerateThumbnail'(通過'Thread.Sleep'),以便每個縮略圖生成需要不同的時間並查看會發生什麼。 – Evk

+2

有關如何異步加載和顯示圖像的示例,您可能需要查看[此答案](http://stackoverflow.com/a/43124089/1136211)。 – Clemens

回答

0

我一言以蔽之解決方案:

首先,你必須設置它的可見性爲false。 比你必須等待所有圖像加載。 您可以使用FrameworkElement.Loaded事件(https://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.loaded(v=vs.110).aspx)。 最後,如果每個圖像都已成功加載,請將其可見性設置爲true。

+0

嘿Nagi,謝謝你的回答。我不想在加載時隱藏圖像,而是希望接口異步加載圖像,並在加載圖像時顯示圖像。 – Bluecakes