Windows Phone - 非同步下載圖片結合Data Binding

Windows Phone - 非同步下載圖片結合Data Binding

這篇文章主要記錄最近在撰寫一個App所遇到的問題,其問題的說明如下:

a. 資料來源只有給圖片的URL,所以需要非同步下載圖片;

b. 利用URL下載圖片時,需要給予帳號密碼驗證;

c. 利用DataBinding方式更新畫面的資料;

 

了解上述三個需求後,該怎麼來處理呢?透過以下的步驟來說明:

 

(1) 建立一個Model用來描述圖片物件的基本資訊

public class image : INotifyPropertyChanged
{
    public string imageId { get; set; }
 
    private string gurl = string.Empty;
 
    public string url
    {
        get { return gurl; }
        set
        {
            gurl = value;
            //進行非同步下載圖像
              AysncDownloadImage();
         }
    }
 
    public string imageDesc { get; set; }
 
    public string imageType { get; set; }
 
    public string isRecommend { get; set; }
 
    public string imageExist { get; set; }
 
    #region 圖片非同步下載+DataBinding功能
    private BitmapImage gimgsource = null;
 
    [IgnoreDataMember]
    public BitmapImage imgsource
    {
        get
        {
            return gimgsource;
        }
        set
        {
            if (value != gimgsource)
            {
                gimgsource = value;
                OnPropertyChanged();
            }
        }
    }
    #endregion
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected virtual void OnPropertyChanged([CallerMemberName] string pPropertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(pPropertyName));
        }
    }
}

     定義物件時多增加獨立屬性「imagesource」宣告為BitmapImage的類型,在set該屬性時多呼叫了OnPropertyChange()

     用於DataBinding之用。另外,在url屬性被set值時,呼叫非同步下載圖像藉由它來set imagesource屬性通知更新畫面。

 

(2) 實作Model中非同步下載圖像並更新BitmapImage屬性值

private AsyncDownloadImage()
{
   try
   {
       WebClient tClient = new WebClient();
       tClient.Credentials = new NetworkCredential("pou", "123456@");
       tClient.OpenReadCompleted += (obj, e) =>
       {
           if (e.Error == null && !e.Cancelled)
           {
               //將下載好的Stream放入BitmapImage,並設定獨立DataBinding的屬性
    this.imgsource = new BitmapImage();
               this.imgsource.SetSource(e.Result);
 
           }
           else
           {
               //代表載入失敗的圖
    Debug.WriteLine(string.Format("Failed,{1}", this.url));
           }
       };
       tClient.OpenReadAsync(new Uri(gurl));
   }
   catch (Exception ex)
   {
       Debug.WriteLine(ex.Message);
   }
}

      該類別實作INotifyPropertyChanged,讓非同步下載完圖片後,藉由修改BitmapImage屬性即直接通知UI進行更新,

      這是MVVM的理念。其中在下載圖片時因為需要予帳號密碼,因而透過NetworkCredential 類別來提供。

 

(3) XAML定義畫面的Binding

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <ListBox x:Name="testListBox">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">    
                    <Grid.ColumnDefinitions>        
                        <ColumnDefinition Width="70*" />        
                        <ColumnDefinition Width="30*" />    
                    </Grid.ColumnDefinitions>    
                    <!--  圖片Binding的是非同步下載圖片更新的imagesource(BitmapImage)屬性,就不是url屬性。 -->    
                    <Image Grid.Column="0" Source="{Binding imagesource}"           
                        Height="100" Width="100" Stretch="UniformToFill" />    
                    <TextBlock x:Name="txtContent" Grid.Column="1" Text="{Binding imageId}" />
                </Grid>        
            </DataTemplate>
        </ListBox.ItemTemplate>       
    </ListBox2>
</Grid>

 

(4) 執行結果:

     005

 

======

以上是分享透過WebClient搭配指定NetworkCredential的方式向指定的URL下載圖片,

最後再搭配DataBinding的方式將圖更新於畫面。這樣的作法主要原因在於非同步下載時需要給予帳號、密碼的部分

如果只是單純透過GET就可以下載的圖片,我就不建議使用這樣的方式,

可以改由直接使用「new Uri("url");」的Uri屬性來DataBinding至畫面上。

希望對大家在處理DataBinding需要圖片時可以有所幫助。

 

References

Converting Stream to byte array after asynchronously downloading in Windows Phone

Image from URL to stream

How to Load an Image from a URL in Windows Phone 8?

WebClient.OpenReadAsync 方法 (Uri, Object)

Asynchronous Image download on Windows Phone 7

How do I download images (jpg) via a webclient and save to isolated storage on Windows Phone 7?

Async Implementation of IValueConverter

Async Implementation of IValueConverter

Silverlight实用示例 - 深入了解Silverlight的IValueConverter和TypeConverter

Silverlight IValueConverter for Image Urls

INotifyPropertyChanged範例

INotifyPropertyChanged 介面

 

Dotblogs 的標籤: