2010-09-27 21 views
1

我有一個WPF列表框,並且每個項目都有該列表需要從服務器上下載的圖像 - 列表定義看起來像這樣:WPF列表框與圖片 - 如何檢測如果圖像沒有下載

<ListBox x:Name="List" BorderThickness="0" AlternationCount="2" ItemContainerStyle="{StaticResource alternatingWithBinding}" 
    HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Hidden"> 
<ListBox.ItemTemplate> 
    <DataTemplate> 
     <Grid x:Name="itemsGrid" Margin="3" ShowGridLines="False" > 
      <Grid.RowDefinitions> 
       <RowDefinition Height="59"/> 
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="45" /> 
       <ColumnDefinition Width="60" /> 
       <ColumnDefinition Width="*" /> 
       <ColumnDefinition Width="150" /> 
      </Grid.ColumnDefinitions> 

      <Button x:Name="btn" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" Tag="{Binding}" 
       CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" /> 
      <Image x:Name="Thumb" Grid.Column="1" Stretch="Uniform" Opacity="1.0" Source="{Binding Path=Image, Converter={StaticResource ImageConverter}}" Height="65" VerticalAlignment="Center"/> 
      <TextBlock x:Name="Name" Grid.Column="2" Padding="2" Margin="17,0" VerticalAlignment="Center" Text="{Binding Path=Name}" 
         Tag="{Binding}" /> 
     </Grid> 
     <DataTemplate.Triggers> 
      ... 
     </DataTemplate.Triggers> 
    </DataTemplate> 
</ListBox.ItemTemplate> 

和轉換器的樣子:

public class ImageConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
      if (value is string) 
      { 
       value = new Uri((string)value); 
      } 

      if (value is Uri) 
      { 
       BitmapImage bi = new BitmapImage(); 
       bi.BeginInit(); 
       bi.DecodePixelWidth = 150; 
       bi.UriSource = value; 
       bi.DownloadFailed += new EventHandler<ExceptionEventArgs>(bi_DownloadFailed); 
       bi.EndInit(); 
       return bi; 
      } 

      return null; 
    } 

這樣做是爲了顯示默認圖像時,sourceUrl返回從服務器什麼。但是因爲我在XAML代碼中使用了轉換器,所以我不知道如何攔截這種情況。我不知道如何攔截這種情況。我看到BitmapImage具有對我來說很完美的DownloadFailed事件,我只是不知道如何在這種情況下使用它。

回答

0

嗯....我相信下載發生在EndInit上,這很重要。由於您正在爲轉換器使用靜態資源,因此每個應用程序最終會有一個實例。這意味着,如果您創建了一個變量作用於類級別並用於存儲下載結果的變量,則在調用轉換之間不注意變量狀態時可能會出現問題。但是,由於UI是在單個線程中呈現的,因此您不必擔心太多。

public class ImageConverter : IValueConverter 
{ 
    private static readonly BitmapImage _default = MakeDefault(); 
    private bool _downloadFailed; 

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
{ 
     if (value is string) 
     { 
      value = new Uri((string)value); 
     } 

     if (value is Uri) 
     { 
      _downloadFailed = false; 
      BitmapImage bi = new BitmapImage(); 
      bi.BeginInit(); 
      bi.DecodePixelWidth = 150; 
      bi.UriSource = value; 
      // the event handler sets _downloadFailed to true! 
      bi.DownloadFailed += bi_DownloadFailed; 
      bi.EndInit(); 
      // unhook so we don't unintentionally keep the instance alive 
      // this is important; you will leak BI instances otherwise! 
      bi.DownloadFailed -= bi_DownloadFailed; 
      if(_downloadFailed)     
       return _default; 
      return bi; 
     } 

     return null; 
} 
+0

感謝。使用你的代碼,DownloadFailed事件根本不會被解僱。當我只將事件掛鉤時(沒有解開它),它確實觸發了,但是我遇到的問題是,在它觸發時,執行已經通過了Convert方法。在處理程序的第一個參數中查看對象時,我得到了實際失敗的url,但我不知道如何將它綁定到列表中的正確項目。 – user350213 2010-09-27 20:32:26

+0

此外,如果我沒有使用轉換器(我必須做其他原因),那麼ImageFailed事件將觸發該項目並在該處理程序中設置默認圖像。是我使用轉換器防止列表項ImageFailed事件觸發的事實? – user350213 2010-09-27 20:45:10

+0

對不起,由於某種原因,這以前沒有開火。它現在做,而且與轉換器無關。 – user350213 2010-09-27 20:51:39

1

你看過Binding類的TargetNullValue屬性嗎?

如果您無法下載文件,我會讓Converter返回null。


public object Convert(object value, Type targetType, 
    object parameter, System.Globalization.CultureInfo culture) 
{ 

    if (parameter.ToString()=="blue") 
    { 
    return new Uri("Butterfly1.png", UriKind.RelativeOrAbsolute); 
    } 
    return null; 
} 

然後安裝在你的綁定指定TargetNullValue在XAML

<Window.Resources> 
<my:ImageConverter x:Key='ImageConverter1' /> 
<BitmapImage x:Key='defaultImage' 
      UriSource='/WpfApplication1;component/default.png' /> 


然後默認圖像。


<Image Source='{Binding Converter={StaticResource ImageConverter1}, 
    ConverterParameter="red",TargetNullValue={StaticResource defaultImage}}' 
     Height='100' /> 
<Image Source='{Binding Converter={StaticResource ImageConverter1}, 
    ConverterParameter="blue",TargetNullValue={StaticResource defaultImage}}' 
     Height='100' /> 

相關問題