带有图像的 WPF 列表框 - 如何检测图像是否未下载
我有一个 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 事件,这对我来说是完美的,我只是不知道如何在这种情况下使用它。
I have a wpf ListBox, and each item has an image that the list needs to download from a server - the list definition looks like so:
<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>
and the converter looks like:
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;
}
The idea is to show a default image when the sourceUrl returns nothing from the server. But since i'm using the converter in the XAML code,
Source="{Binding Path=Image, Converter={StaticResource ImageConverter}}"
I'm not sure how to intercept that case. I see that BitmapImage has the DownloadFailed event which is perfect for me, I just don't know how to use that in this context.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您看过 Binding 类 TargetNullValue 属性吗?
如果您无法下载该文件,我会让转换器返回 null。
然后在 XAML 中设置默认图像
然后在绑定中指定 TargetNullValue。
Have you looked at the Binding class TargetNullValue property?
I'd have the Converter return null if you can't download the file.
Then setup a default image in the XAML
Then in your binding specify the TargetNullValue.
嗯...我相信下载发生在 EndInit 上,这很重要。由于您使用转换器的静态资源,因此最终每个应用程序都有一个实例。这意味着,如果您创建一个作用域为类级别的变量并使用它来存储下载结果,如果您不小心调用 Convert 之间的变量状态,则可能会出现问题。不过,由于 UI 是在单线程中渲染的,因此您不必太担心。
Hmmm.... I believe download occurs on EndInit, which matters. Since you're using a static resource for a converter, you end up having a single instance per application. That means if you create a variable scoped to the class-level and use that to store the results of the download, you can have issues if you aren't careful with the state of your variables between calls to Convert. However, since the UI is rendered in a single thread, you don't have to worry too much.