为WPF Image类提供初始图像占位符

时间:2011-08-10 07:37:15

标签: wpf wpf-controls binding styles wpftoolkit

当我运行项目时出现运行时错误: 错误:必须设置属性'UriSource'或属性'StreamSource'。 因为this.ImageUri为null,我不知道为什么这个.ImageUri为null!帮助我

我一直在使用图像作为我的列表框项目使用WPF ListBox。源图像路径指向托管这些图像的服务器。在快速网络上,图像出现时没有任何明显的延迟。然而,在慢速链接中,用户体验降级后变得明显,我真的想在下载和解码图像时显示占位符图像。

令人惊讶的是,我没有在博客圈中找到这个问题的解决方案,所以我编写了一个派生类来解决这个问题。

下面的示例XAML来自我的项容器样式。我用我的本地类实现local替换了Image:ImageLoader。

<Window.Resources>
<DataTemplate DataType="{x:Type local:MyData}">
...
<StackPanel Grid.Column="0" Margin="5">
<Border BorderThickness="0">
<MyControl:ImageLoader Width="50" Height="50" ImageUri="{Binding Path=profile_image_url_https, FallbackValue=profile_image_url_https}" InitialImage="/MyProject;component/Images/nopic.png"  HorizontalAlignment="Left"></imgz:ImageLoader>
</Border>
</StackPanel>
...
</DataTemplate>
</Window.Resources>

<Grid>
<ListBox ItemsSource="{Binding Source = {StaticResource MyData}}"    />
</Grid>

处理初始图像的核心是在OnLoaded()方法中,我使用BitmapImage作为源,并将UriSource设置为派生类'ImageUri依赖属性,它允许数据绑定。下载完成或收到故障事件时,初始映像将更新为实际映像。该类还可以选择指定“LoadFailedImage”。

public class ImageLoader : Image
{
    public static readonly DependencyProperty ImageUriProperty = DependencyProperty.Register(
        "ImageUri", typeof(Uri), typeof(ImageLoader), new PropertyMetadata(null, null));

    private BitmapImage loadedImage;

    public ImageLoader()
    {
        this.Loaded += this.OnLoaded;
    }

    public string LoadFailedImage
    {
        get;
        set;
    }

    public Uri ImageUri
    {
        get {return this.GetValue(ImageUriProperty) as Uri;}
        set {this.SetValue(ImageUriProperty, value);}
    }

    public string InitialImage
    {
        get;
        set;
    }

    private new ImageSource Source
    {
        get {return base.Source;}
        set {base.Source = value;}
    }

    private void OnLoaded(object sender, RoutedEventArgs e)
    {
        // Loading the specified image            
        this.loadedImage = new BitmapImage();
        this.loadedImage.BeginInit();
        this.loadedImage.CacheOption = BitmapCacheOption.OnDemand;
        this.loadedImage.DownloadCompleted += this.OnDownloadCompleted;
        this.loadedImage.DownloadFailed += this.OnDownloadFailed;
        this.loadedImage.UriSource = this.ImageUri;
        this.loadedImage.EndInit();

        // The image may be cached, in which case we will not use the initial image
        if (!this.loadedImage.IsDownloading)
        {
            this.Source = this.loadedImage;
        }
        else
        {
            // Create InitialImage source if path is specified
            if (!string.IsNullOrWhiteSpace(this.InitialImage))
            {
                BitmapImage initialImage = new BitmapImage();

                // Load the initial bitmap from the local resource
                initialImage.BeginInit();
                initialImage.UriSource = new Uri(this.InitialImage, UriKind.Relative);
                initialImage.DecodePixelWidth = (int)this.Width;
                initialImage.EndInit();

                // Set the initial image as the image source
                this.Source = initialImage;                
            }
        }

        e.Handled = true;
    }

    private void OnDownloadFailed(object sender, ExceptionEventArgs e)
    {
        if (!string.IsNullOrWhiteSpace(this.LoadFailedImage))
        {
            BitmapImage failedImage = new BitmapImage();

            // Load the initial bitmap from the local resource
            failedImage.BeginInit();
            failedImage.UriSource = new Uri(this.LoadFailedImage, UriKind.Relative);
            failedImage.DecodePixelWidth = (int)this.Width;
            failedImage.EndInit();
            this.Source = failedImage;
        }
    }

    private void OnDownloadCompleted(object sender, EventArgs e)
    {
        this.Source = this.loadedImage;
    }
}

当我运行项目时出现运行时错误: 错误:必须设置属性'UriSource'或属性'StreamSource'。 因为this.ImageUri为null,我不知道为什么这个.ImageUri为null!帮助我

1 个答案:

答案 0 :(得分:2)

如果它不是InitialImage =“/ MyProject; component / Images / nopic.png”中的分号拼写错误,
也许最好在ImageUri中将InitialImage设置为Default

 public static readonly DependencyProperty ImageUriProperty = DependencyProperty.Register(
    "ImageUri", typeof(Uri), typeof(ImageLoader), new PropertyMetadata(new Uri("/MyProject/component/Images/nopic.png"), null));


更新:

您必须绑定到Image.Source,并且可以使用PriorityBinding来显示占位符。

<Image.Source>
    <PriorityBinding>
        <!--highest priority sources are first in the list-->
        <Binding Path="YourImageUri"
           IsAsync="True" />
        <Binding Path="InitialImageUri"
           IsAsync="True" />
    </PriorityBinding>
</Image.Source>

对于“LoadFailedImage”,a将归属于Image.ImageFailed事件
希望这会有所帮助。