2011-08-10 38 views
0

當我運行項目時出現運行時錯誤ocure: 錯誤:屬性'UriSource'或屬性'StreamSource'必須設置。 因爲this.ImageUri爲null,我不知道爲什麼this.ImageUri爲null!幫我爲WPF圖像類提供初始圖像佔位符

我一直在使用WPF ListBox使用圖像作爲我的列表框項目。源圖像路徑指向託管這些圖像的服務器。在快速網絡中,圖像沒有任何明顯的延遲。然而,慢速鏈接顯示用戶體驗下降,我真的想在圖像下載和解碼時顯示佔位符圖像。

令人驚訝的是,我沒有在這個問題的博客上找到解決方案,所以我編寫了一個派生類來解決這個問題。

下面的示例XAML來自我的項目容器樣式。我用本地的本地類實現替換了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; 
    } 
} 

當我運行該項目運行時錯誤ocured: 錯誤:屬性「UriSource」或財產「的StreamSource」必須設置。 因爲this.ImageUri爲null,我不知道爲什麼this.ImageUri爲null!幫我

回答

2

如果不是在InitialImage =分號錯字 「/ MyProject的;組件/圖片/ nopic.png」,
也許這是更好地設置您的InitialImage爲默認的ImageUri

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


UPDATE:

你必須綁定到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」,將會潛水到Image.ImageFailed事件。

希望這會有所幫助。

+0

不起作用,問題在於this.loadedImage.UriSource = this.ImageUri;線,ImageUri沒有綁定 – ArMaN

+0

好吧。請參閱http://msdn.microsoft.com/en-us/library/ms619218.aspx中的註釋。 「屬性更改只能在對象初始化期間發生」。我不相信綁定知道:) – LPL

+0

我已經更新了我的答案。 – LPL