2013-04-16 20 views
7

Gravatar-Imagesを読み込み、コードビハインドからWPF Image-Controlに設定したいと思います。 だから、コードはGetGravatarImageがどのように見えるWPF画像を非同期にする

imgGravatar.Source = GetGravatarImage(email); 

次のようになります。

BitmapImage bi = new BitmapImage(); 
bi.BeginInit(); 
bi.UriSource = new Uri(GravatarImage.GetURL("http://www.gravatar.com/avatar.php?gravatar_id=" + email) , UriKind.Absolute); 
bi.EndInit(); 
return bi; 

ネットワーク接続が遅い場合残念ながら、これはGUIをロックします。イメージソースを割り当て、UIをブロックすることなくバックグラウンドでイメージを読み込ませる方法はありますか?

ありがとうございます!

答えて

0

あなたはこの質問を見てみたいことがあります

Link

を、私はAsynchroneタスクを起動することをお勧めします、そのタスクでasyncを指定するために必要なコードを入れてしまうでしょう。

19

XAMLのimgGravatarでバインディングを使用することをお勧めします。 IsAsync = trueを設定すると、WPFはスレッドプールのスレッドを自動的に利用して画像を取得します。あなたはIValueConverterに解決するロジックをカプセル化し、単にXAMLでソース

として電子メールを結合することができる:

コードで
<Window.Resouces> 
    <local:ImgConverter x:Key="imgConverter" /> 
</Window.Resource> 

... 


<Image x:Name="imgGravatar" 
     Source="{Binding Path=Email, 
         Converter={StaticResource imgConverter}, 
         IsAsync=true}" /> 

public class ImgConverter : IValueConverter 
{ 
    public override object Convert(object value, ...) 
    { 
     if (value != null) 
     { 
      BitmapImage bi = new BitmapImage(); 
      bi.BeginInit(); 
      bi.UriSource = new Uri( 
       GravatarImage.GetURL(
        "http://www.gravatar.com/avatar.php?gravatar_id=" + 
         value.ToString()) , UriKind.Absolute 
       ); 
      bi.EndInit(); 
      return bi;     
     } 
     else 
     { 
      return null; 
     } 

    } 
} 
+1

のBitmapImageはまた、あなたのBeginInitの/ EndInitコールを救う(http://msdn.microsoft.com/en-us/library/ms602473.aspx)[URIパラメータを持つコンストラクタ]を、持っています。 – Clemens

+0

+1はそれについて知りませんでした、いいヒント。私はちょうど著者からのコードをコピーし、実際のダウンロードを最適化する方法については考えていませんでした。代わりに、UIブロックの問題を優雅な方法で解決することに焦点を当てました(もちろんコードが非同期でない場合はブロックします)。繰り返し使用すると、コンバーターは電子メールの代わりにバインディングから完全なURLを再利用できるようにすることもできます。あなたがディスパッチを常に管理しなければならないので、私は 'ThreadPool'を使って嫌いです。これは純粋なMVVMアプリケーションのために私には十分にエレガントではありません。 – JanW

+0

BitmapImageを作成すると非同期に呼び出されないとブロックされる理由を説明できますか?それではなぜIsDownloadingプロパティと 'DownloadCompleted'イベントがありますか? XAMLのImageコントロールの 'Source'プロパティをWeb上の大きな画像を参照するURLに設定するだけでは、UIはブロックされません。代わりに、WPFはバックグラウンドでイメージをダウンロードし、ダウンロードが終了するとすぐにイメージを表示します。 – Clemens

6

あなたのコードがブロックされる理由は、私が見ることができませんBitmapImageはバックグラウンドでの画像データのダウンロードをサポートしているため、UIを使用できます。そのため、IsDownloadingプロパティとDownloadCompletedイベントがあります。

とにかく、次のコードは、別のスレッド(ThreadPool)から完全にダウンロードしてイメージを作成する簡単な方法を示しています。そのバッファからBitmapImageを作成する前に、WebClientインスタンスを使用してイメージバッファ全体をダウンロードします。 BitmapImageが作成された後、UIスレッドからアクセスできるように、Freezeが呼び出されます。最後に、ImageコントロールのSourceプロパティをDispatcher.BeginInvoke呼び出しによってUIスレッドに割り当てます。

ThreadPool.QueueUserWorkItem(
    o => 
    { 
     var webClient = new WebClient(); 
     var url = GravatarImage.GetURL("http://www.gravatar.com/avatar.php?gravatar_id=" + email); 
     var buffer = webClient.DownloadData(url); 
     var bitmapImage = new BitmapImage(); 

     using (var stream = new MemoryStream(buffer)) 
     { 
      bitmapImage.BeginInit(); 
      bitmapImage.CacheOption = BitmapCacheOption.OnLoad; 
      bitmapImage.StreamSource = stream; 
      bitmapImage.EndInit(); 
      bitmapImage.Freeze(); 
     } 

     Dispatcher.BeginInvoke((Action)(() => image.Source = bitmapImage)); 
    }); 
関連する問題