[英]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.