2011-08-10 12 views
0

プロジェクトを実行するときに実行時エラーが発生しました: エラー:プロパティ 'UriSource'またはプロパティ 'StreamSource'を設定する必要があります。 this.ImageUriがnullなので、なぜthis.ImageUriがnullになるのかわかりません!助けてくださいWPF Imageクラスの最初の画像プレースホルダを提供

私はリストボックスのアイテムとして画像を使ってWPF ListBoxを使っています。ソースイメージパスは、それらのイメージをホストするサーバーを指します。高速ネットワークでは、画像は目立たない遅延なく現れた。しかし、ゆっくりとしたリンクでは、ユーザーエクスペリエンスが低下し、イメージがダウンロードされてデコードされている間にプレースホルダイメージが表示されたかったことが明らかになりました。

驚いたことに、私はこの問題のためにブログ圏で解決策を見つけられなかったので、これに対処するために派生クラスをコーディングしました。

以下のサンプルXAMLは、私のアイテムコンテナスタイルのものです。私はImageを自分のローカルクラス実装local:ImageLoaderに置き換えました。最初の画像に対する処理の心臓は、私はソースとしてのBitmapImageを使用して、データバインディングを可能にする派生クラスImageUri依存プロパティにUriSource設定OnLoaded()メソッドである

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

。ダウンロードが完了したとき、または失敗イベントが受信されたときに、初期イメージが実際のイメージに更新されます。クラスでは、オプションで "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になるのかわかりません!それはInitialImage =でセミコロンのタイプミスではない場合、私に

答えて

2

を助ける「/ MyProjectと、コンポーネント/イメージ/ nopic.png」、
は、多分ImageUri

public static readonly DependencyProperty ImageUriProperty = DependencyProperty.Register(
    "ImageUri", typeof(Uri), typeof(ImageLoader), new PropertyMetadata(new Uri("/MyProject/component/Images/nopic.png"), null)); 
でデフォルトとしてあなたInitialImageを設定する方が良いでしょう


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

関連する問題