Gif画像をListBox.ItemTemplateに追加する場合
-
2012年2月2日 14:39
いつもお世話になっております、Samrilと申します。
前回、ImageToolを使い、非同期通信で取得したGifファイルURLからGifファイルデータを読み込み、Bitmapに変換する方法を教わりました。
今回は、そのデータをListBoxに表示する方法を探しております。
WebClientから取得したデータをListで表示するとき、そのデータにある画像URLがGifの場合、どのようにすればいいのでしょうか?
※ pngやjpgの場合は、Bindingした際に自動的に取得してくれますが、Windows PhoneはGifに対応していないため
XAMLの一部抜粋
<ListBox Name="ItemListBox"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Vertical" Width="Auto" Height="Auto"> <Image Source="{Binding GifImage}" Height="100" Width="100"/> <TextBlock Text="{Binding GifText}" VerticalAlignment="Top"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
CSの一部抜粋
// コンストラクター public MainPage() { InitializeComponent(); // なんでもいいので、いったんWebClientで非同期をおこなう WebClient client = new WebClient(); client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted); client.DownloadStringAsync(new Uri("http://**********.xml", UriKind.Absolute)); } void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { /////////////////////////////////////////////////////// // WebClientの結果が次のようにGif画像のURLとテキストだった場合 // <GifImage>http://***********.gif // <GifText>これはGifファイルです // // どのようにしてItemListBox.ItemsSourceにデータを格納できるのか? /////////////////////////////////////////////////////// // WebClientの結果をバインド用のクラスに変換する List<ItemList> itemList = ........; // XAMLのListBox.ItemTemplateにデータを格納する ItemListBox.ItemsSource = itemList; } // Bind用クラス public class ItemList { public string GifImage{get;set;} public string GifText{get;set;} }
分かりづらい文章で申し訳ありませんが、ご教授をお願いいたします。
また、意味がわからないなどがありましたら、お気軽にご返信ください。
- 移動 MikeWangytMicrosoft Contingent Staff, Administrator 2012年10月2日 11:14 (移動元:Windows Phone 7 向けの開発)
すべての返信
-
2012年2月3日 16:20
苦肉の策ですが、試したソースを紹介します。
ほんとはもっとスマートな方法があるんじゃないの?と思ってますが、とりあえず他の方が回答されるまでのつなぎとして
Samrilさんのソースをベースに、Twitterのフォロワーから名前とimageを表示するようなコードを書いてみました
以下のコードでは2種類の方法を試しています。xamlのコメントアウトを変更して処理を切り替えることができます
(1) _GifImage をバインドするxamlコードを有効にすると bind時にbitmapを返す処理をします。(ただし、このままだとGIFだけしか読めません)
(2) GifImage をバインドするxamlコードを有効にすると、通常のイメージのロードに失敗した= UrlがGIFを指しているを想定して、ImageFailedイベント内でGIFファイルをロードし直す処理をします。(ほとんどのUrlがjpegで、たまにgifが混ざっているような場合を想定)
Mainpage.xaml
<phone:PhoneApplicationPage x:Class="PhoneAppGifTest.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True"> <!--LayoutRoot は、すべてのページ コンテンツが配置されるルート グリッドです--> <Grid x:Name="LayoutRoot" Background="SteelBlue"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel は、アプリケーション名とページ タイトルを格納します--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="マイ アプリケーション" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="ページ名" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel - 追加コンテンツをここに入力します--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ListBox Name="ItemListBox"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Vertical" Width="Auto" Height="Auto"> <!-- BitmapImageを返す方法 --> <Image Source="{Binding _GifImage}" Height="100" Width="100" /> <!-- Image_ImageFailedで処理する方法 --> <!--<Image Source="{Binding _GifImage}" Height="100" Width="100" ImageFailed="Image_ImageFailed" />--> <TextBlock Text="{Binding GifText}" VerticalAlignment="Top"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Grid> <!--ApplicationBar の使用法を示すサンプル コード--> <!--<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="MenuItem 1"/> <shell:ApplicationBarMenuItem Text="MenuItem 2"/> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>--> </phone:PhoneApplicationPage>
Mainpage.xaml.csusing System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Phone.Controls; using System.Xml.Linq; using ImageTools.IO.Gif; using ImageTools; namespace PhoneAppGifTest { public partial class MainPage : PhoneApplicationPage { // コンストラクター public MainPage() { InitializeComponent(); ImageTools.IO.Decoders.AddDecoder<GifDecoder>(); WebClient client = new WebClient(); client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted); client.DownloadStringAsync(new Uri("https://api.twitter.com/1/statuses/friends.xml?screen_name=konoxl", UriKind.Absolute)); } void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { List<ItemList> itemList = new List<ItemList>(); WebClient client = sender as WebClient; XDocument doc = XDocument.Parse(e.Result); foreach (var n in doc.Elements().Descendants("user").Select(p => new { name = p.Element("name").Value, image = p.Element("profile_image_url").Value })) { itemList.Add(new ItemList() { GifText = n.name, GifImage = n.image }); } ItemListBox.ItemsSource = itemList; } private void Image_ImageFailed(object sender, ExceptionRoutedEventArgs e) { //AG_E_NETWORK_ERROR AG_E_UNKNOWN_ERROR if (e.ErrorException.Message != "AG_E_UNKNOWN_ERROR") return; Image obj = sender as Image; if (obj != null && obj.Source is System.Windows.Media.Imaging.BitmapImage) { ExtendedImage image = new ExtendedImage(); image.LoadingCompleted += (s, ex) => { this.Dispatcher.BeginInvoke(() => { obj.Source = image.ToBitmap(); }); }; image.UriSource = ((System.Windows.Media.Imaging.BitmapImage)obj.Source).UriSource; } } } }
バインドしたImageのロードに失敗したときに Image_ImageFailed イベントが起きますが、AG_E_NETWORK_ERROR と AG_E_UNKNOWN_ERROR の2回飛んできます。
良くわからないけど取り合えずAG_E_UNKNOWN_ERRORの時だけ ImageToolsの力を借りてGIF画像をロードします。
(本当なら、例外処理とか入れないといけないと思う)
ItemList.cs
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Media.Imaging; using ImageTools; using System.ComponentModel; namespace PhoneAppGifTest { public class ItemList { public BitmapImage _GifImage { get { BitmapImage bmp = new BitmapImage(); ExtendedImage image = new ExtendedImage(); image.LoadingCompleted += (s,args) => { bmp.Dispatcher.BeginInvoke(() => { if (bmp.PixelHeight == 0) { bmp.SetSource(image.ToStream()); //System.Diagnostics.Debug.WriteLine(bmp.UriSource); } }); }; image.UriSource = new Uri(this.GifImage, UriKind.RelativeOrAbsolute); return bmp; } } public string GifImage { get; set; } public string GifText { get; set; } } }
_GifImageプロパティのGet処理でとりあえず BitmapImageを返して置いて、LoadingCompletedイベント時に bmp.SetSource(image.ToStream()); してます。 -
2012年2月3日 18:52
こんばんは、CH3COOH(酢酸)です。
konox1さんのようにシンプルに書けず、回答に時間が掛かってしまいました。申し訳ございません。
デフォルトでgifファイルのデコーダーがないとこんなに大変だとは……ダウンロードしたGIFファイルをキャッシュ画像として分離ストレージに保存して、
コンバーターを使って、バインディングしたファイルパスからBitmapImageオブジェクトへ変換し、
ListBoxコントロール上でGIFファイルを表示するようにしてみました。利用側からはコレクションにURLを入れておくだけで、
ダウンロードとキャッシュと表示をしてくれるので、そこそこコードを流用して頂けるのではないかと思います。MainPage.xamlです。
<phone:PhoneApplicationPage x:Class="GifTest.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:GifTest" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True" Language="ja-JP"> <!--LayoutRoot は、すべてのページ コンテンツが配置されるルート グリッドです--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel は、アプリケーション名とページ タイトルを格納します--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="SOFTBUILD" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="gif test" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel - 追加コンテンツをここに入力します--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ListBox Name="listBox1"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Vertical" Width="Auto" Height="Auto"> <Image Height="200" Width="200" Stretch="UniformToFill"> <Image.Source> <Binding Path="CachePath" Mode="TwoWay"> <Binding.Converter> <local:StringToImagerConverter/> </Binding.Converter> </Binding> </Image.Source> </Image> <TextBlock Text="{Binding Text}" VerticalAlignment="Top"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Grid> <!--ApplicationBar の使用法を示すサンプル コード--> <!--<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="MenuItem 1"/> <shell:ApplicationBarMenuItem Text="MenuItem 2"/> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>--> </phone:PhoneApplicationPage>
次にバインディング用のクラスListBoxにバインディングするクラスを定義します。コンストラクタに設定されたURLの画像ファイルをダウンロードしてキャッシュします。
using System.ComponentModel; using System.IO.IsolatedStorage; using System.Net; using Microsoft.Phone.Reactive; namespace GifTest { public class ImageInfo : INotifyPropertyChanged { public ImageInfo(string url, string text) { ImageURL = url; Text = text; var fileName = System.IO.Path.GetFileName(url); using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { // 既に画像ファイルがある場合はダウンロードしにいかない if (store.FileExists(fileName)) { CachePath = fileName; return; } } // urlが入ったら画像をダウンロードして、分離ストレージに保存する HttpWebRequest req = HttpWebRequest.CreateHttp(url); Observable.FromAsyncPattern<WebResponse>(req.BeginGetResponse, req.EndGetResponse)() .Select(res => res.GetResponseStream()) .Select(strm => { var cacheFileName = System.IO.Path.GetFileName(url); using (var store = IsolatedStorageFile.GetUserStoreForApplication()) using (var strmWriter = store.CreateFile(cacheFileName)) { var bytes = new byte[128]; int readed = 0; while (true) { readed = strm.Read(bytes, 0, bytes.Length); if (readed == 0) break; strmWriter.Write(bytes, 0, readed); } } strm.Close(); return cacheFileName; }) .ObserveOnDispatcher() .Subscribe(cacheFileName => CachePath = cacheFileName); } public string ImageURL { get; set; } public string Text { get; set; } private string _cachePath; public string CachePath { get { return _cachePath; } set { _cachePath = value; OnPropertyChanged("CachePath"); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string name) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } } }
ListBoxにバインドしたキャッシュのファイルパスからBitmapImageオブジェクトへ変換するコンバーターを用意します。ファイルパスの拡張子部分がgifだった場合はImage Toolsを使用して、それ以外の場合はそのままストリームをBitmapImageに設定するようにしました。using System; using System.Globalization; using System.IO; using System.IO.IsolatedStorage; using System.Windows.Data; using System.Windows.Media.Imaging; using ImageTools; using ImageTools.IO.Gif; namespace GifTest { public class StringToImagerConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var filePath = value as string; if (filePath == null) { return null; } var bmp = new BitmapImage(); using (var store = IsolatedStorageFile.GetUserStoreForApplication()) using (var strm = store.OpenFile(filePath, FileMode.Open)) { var ext = System.IO.Path.GetExtension(filePath); if (ext.ToLower() == ".gif") { // 拡張子がgifの場合はImageToolsを使用する ExtendedImage image = new ExtendedImage(); var decoder = new GifDecoder(); decoder.Decode(image, strm); bmp.SetSource(image.ToStream()); } else { // 拡張子がgif以外の場合はImageToolsを // そのままBitmapImageにストリームを食わせる bmp.SetSource(strm); } } return bmp; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } }
あとは、ListBoxにバインドする元ネタのコレクションを作成して、ItemSourceに設定して終わりです。using System; using System.Collections.ObjectModel; using System.IO; using System; using System.Collections.ObjectModel; using System.IO; using System.IO.IsolatedStorage; using System.Windows; using System.Windows.Navigation; using ImageTools.IO; using ImageTools.IO.Gif; using Microsoft.Phone.Controls; namespace GifTest { public partial class MainPage : PhoneApplicationPage { // コンストラクター public MainPage() { InitializeComponent(); // デコーダーを追加する Decoders.AddDecoder<GifDecoder>(); } protected override void OnNavigatedTo(NavigationEventArgs e) { var list = new ObservableCollection<ImageInfo>(); list.Add(new ImageInfo("https://p.twimg.com/AkKIvbKCQAACN04.jpg", "てすと1")); list.Add(new ImageInfo("https://p.twimg.com/Acg5qLwCMAEiBW-.jpg", "てすと2")); list.Add(new ImageInfo("http://ch3cooh.jp/files/sample_gif/image01.gif", "てすと3")); list.Add(new ImageInfo("http://ch3cooh.jp/files/sample_gif/image02.gif", "てすと4")); list.Add(new ImageInfo("http://ch3cooh.jp/files/sample_gif/image03.gif", "てすと5")); list.Add(new ImageInfo("http://ch3cooh.jp/files/sample_gif/image04.gif", "てすと6")); list.Add(new ImageInfo("http://ch3cooh.jp/files/sample_gif/image05.gif", "てすと7")); list.Add(new ImageInfo("http://ch3cooh.jp/files/sample_gif/image06.gif", "てすと8")); list.Add(new ImageInfo("http://ch3cooh.jp/files/sample_gif/image07.gif", "てすと9")); listBox1.ItemsSource = list; } } }
- 回答としてマーク Samril 2012年2月5日 9:19
-
2012年2月4日 1:04
酢酸さんの回答を見て IValueConverterを使うように書き換えてみました
MainPage.xaml
<phone:PhoneApplicationPage x:Class="PhoneAppGifTest.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True" xmlns:my="clr-namespace:PhoneAppGifTest"> <phone:PhoneApplicationPage.Resources> <my:StringToImagerConverter x:Key="StringToImagerConverter1" /> </phone:PhoneApplicationPage.Resources> <!--LayoutRoot は、すべてのページ コンテンツが配置されるルート グリッドです--> <Grid x:Name="LayoutRoot" Background="SteelBlue"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel は、アプリケーション名とページ タイトルを格納します--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="マイ アプリケーション" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="ページ名" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel - 追加コンテンツをここに入力します--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ListBox Name="ItemListBox"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Vertical" Width="Auto" Height="Auto"> <!-- BitmapImageを返す方法 --> <!--<Image Source="{Binding _GifImage}" Height="100" Width="100" />--> <!-- Image_ImageFailedで処理する方法 --> <!--<Image Source="{Binding _GifImage}" Height="100" Width="100" ImageFailed="Image_ImageFailed" />--> <!--コンバータで処理する方法--> <Image Source="{Binding Path=GifImage, Converter={StaticResource StringToImagerConverter1}}" Height="100" Width="100" /> <TextBlock Text="{Binding GifText}" VerticalAlignment="Top"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Grid> <!--ApplicationBar の使用法を示すサンプル コード--> <!--<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="MenuItem 1"/> <shell:ApplicationBarMenuItem Text="MenuItem 2"/> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>--> </phone:PhoneApplicationPage>
Bind にコンバータを追加。
MainPage.xaml.cs
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Phone.Controls; using System.Xml.Linq; using ImageTools.IO.Gif; using ImageTools; using System.Windows.Data; using System.Windows.Media.Imaging; namespace PhoneAppGifTest { public partial class MainPage : PhoneApplicationPage { // コンストラクター public MainPage() { InitializeComponent(); ImageTools.IO.Decoders.AddDecoder<GifDecoder>(); WebClient client = new WebClient(); client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted); client.DownloadStringAsync(new Uri("https://api.twitter.com/1/statuses/friends.xml?screen_name=konoxl", UriKind.Absolute)); } void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { List<ItemList> itemList = new List<ItemList>(); WebClient client = sender as WebClient; XDocument doc = XDocument.Parse(e.Result); foreach (var n in doc.Elements().Descendants("user").Select(p => new { name = p.Element("name").Value, image = p.Element("profile_image_url").Value })) { itemList.Add(new ItemList() { GifText = n.name, GifImage = n.image }); } ItemListBox.ItemsSource = itemList; } //private void Image_ImageFailed(object sender, ExceptionRoutedEventArgs e) //{ // //AG_E_NETWORK_ERROR AG_E_UNKNOWN_ERROR // if (e.ErrorException.Message != "AG_E_UNKNOWN_ERROR") // return; // Image obj = sender as Image; // if (obj != null && obj.Source is System.Windows.Media.Imaging.BitmapImage) // { // ExtendedImage image = new ExtendedImage(); // image.LoadingCompleted += (s, ex) => // { // this.Dispatcher.BeginInvoke(() => // { // obj.Source = image.ToBitmap(); // }); // }; // image.UriSource = ((System.Windows.Media.Imaging.BitmapImage)obj.Source).UriSource; // } //} } public class StringToImagerConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var filePath = value as string; if (filePath == null) { return null; } BitmapImage bmp = new BitmapImage(); if (System.IO.Path.GetExtension(filePath) == ".gif") { ExtendedImage image = new ExtendedImage(); image.LoadingCompleted += (s, args) => { bmp.Dispatcher.BeginInvoke(() => { bmp.SetSource(image.ToStream()); System.Diagnostics.Debug.WriteLine("Loaded Gif {0}", filePath); }); }; image.UriSource = new Uri(filePath, UriKind.RelativeOrAbsolute); } else { bmp.UriSource = new Uri(filePath, UriKind.RelativeOrAbsolute); System.Diagnostics.Debug.WriteLine("Loaded other {0}", filePath); } return bmp; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } }
IValueConverter を追加しました。拡張子で処理を変えるようにもしてみました
ItemList.cs
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; //using System.Windows.Media.Imaging; //using ImageTools; //using System.ComponentModel; namespace PhoneAppGifTest { public class ItemList { //public BitmapImage _GifImage //{ // get // { // BitmapImage bmp = new BitmapImage(); // ExtendedImage image = new ExtendedImage(); // image.LoadingCompleted += (s,args) => { // bmp.Dispatcher.BeginInvoke(() => // { // if (bmp.PixelHeight == 0) // { // bmp.SetSource(image.ToStream()); // System.Diagnostics.Debug.WriteLine(bmp.UriSource); // } // }); // }; // image.UriSource = new Uri(this.GifImage, UriKind.RelativeOrAbsolute); // return bmp; // } //} public string GifImage { get; set; } public string GifText { get; set; } } }
コンバータで処理するのでデータクラスにimageの処理はいらなくなってすっきりしました
キャッシュ処理はいれてませんが、これで昨日私が書いたソースよりは多少ましになったと思います

