繁体   English   中英

具有图像的WPF列表框-如何检测图像是否未下载

[英]WPF Listbox with images - how to detect if an image didn't download

我有一个wpf ListBox,每个项目都有一个列表需要从服务器下载的图像-列表定义如下所示:

<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代码中使用转换器,

Source="{Binding Path=Image, Converter={StaticResource ImageConverter}}"

我不确定如何拦截这种情况。 我看到BitmapImage具有DownloadFailed事件,这对我来说是完美的,我只是不知道如何在这种情况下使用它。

您是否查看了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;
}

然后在XAML中设置默认图像

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


然后在绑定中指定TargetNullValue。


 <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' />

嗯...。我认为下载发生在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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM