// Boston, MA 02110-1301, USA.
using System;
-using System.Drawing;
-using System.Net;
-using System.Windows.Forms;
+using System.Net.Http;
+using System.Runtime.Serialization;
using System.Threading.Tasks;
+using System.Windows.Forms;
namespace OpenTween
{
+ [Serializable]
public class ImageListViewItem : ListViewItem
{
protected readonly ImageCache imageCache;
protected readonly string imageUrl;
+ /// <summary>
+ /// 状態表示に使用するアイコンのインデックスを取得・設定する。
+ /// </summary>
+ /// <remarks>
+ /// StateImageIndex は不必要な処理が挟まるため、使用しないようにする。
+ /// </remarks>
+ public int StateIndex { get; set; }
+
private WeakReference imageReference = new WeakReference(null);
+ private Task imageTask = null;
public event EventHandler ImageDownloaded;
}
public ImageListViewItem(string[] items, ImageCache imageCache, string imageUrl)
- : base(items, imageUrl)
+ : base(items)
{
this.imageCache = imageCache;
this.imageUrl = imageUrl;
+ this.StateIndex = -1;
- if (imageCache != null)
- {
- var image = imageCache.TryGetFromCache(imageUrl);
+ var image = imageCache?.TryGetFromCache(imageUrl);
+
+ if (image != null)
+ this.imageReference.Target = image;
+ }
+
+ protected ImageListViewItem(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
- if (image == null)
- this.GetImageAsync();
- else
- this.imageReference.Target = image;
+ public Task GetImageAsync(bool force = false)
+ {
+ if (this.imageTask == null || this.imageTask.IsCompleted)
+ {
+ this.imageTask = this.GetImageAsyncInternal(force);
}
+
+ return this.imageTask;
}
- private Task GetImageAsync(bool force = false)
+ private async Task GetImageAsyncInternal(bool force)
{
if (string.IsNullOrEmpty(this.imageUrl))
- return Task.FromResult(0);
+ return;
- var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
+ if (!force && this.imageReference.Target != null)
+ return;
- return this.imageCache.DownloadImageAsync(this.imageUrl, force)
- .ContinueWith(t =>
- {
- if (t.IsFaulted)
- {
- t.Exception.Flatten().Handle(x => x is WebException || x is InvalidImageException || x is TaskCanceledException);
- return;
- }
+ try
+ {
+ var image = await this.imageCache.DownloadImageAsync(this.imageUrl, force);
- this.imageReference.Target = t.Result;
+ this.imageReference.Target = image;
- if (this.ListView == null || !this.ListView.Created || this.ListView.IsDisposed)
- return;
+ if (this.ListView == null || !this.ListView.Created || this.ListView.IsDisposed)
+ return;
- if (this.Index < this.ListView.VirtualListSize)
- {
- this.ListView.RedrawItems(this.Index, this.Index, true);
+ if (this.Index < this.ListView.VirtualListSize)
+ {
+ this.ListView.RedrawItems(this.Index, this.Index, true);
- if (this.ImageDownloaded != null)
- this.ImageDownloaded(this, EventArgs.Empty);
- }
- }, uiScheduler);
+ this.ImageDownloaded?.Invoke(this, EventArgs.Empty);
+ }
+ }
+ catch (HttpRequestException) { }
+ catch (InvalidImageException) { }
+ catch (TaskCanceledException) { }
}
public MemoryImage Image
}
}
- public void RefreshImage()
+ public Task RefreshImageAsync()
{
this.imageReference.Target = null;
- this.GetImageAsync(true);
+ return this.GetImageAsync(true);
}
}
}