Преобразователь привязки всегда выполняется в потоке пользовательского интерфейса.Таким образом, вы можете запустить другой поток в методе Convert, но в конечном итоге (так как вам нужна обратная связь с этим потоком), вам придется ждать, пока он не завершится, тем самым вы блокируете свое приложение.
Например, для решения этой проблемы вы можете использовать свойство Binding.IsAsync :
public class ListItemViewData
{
private readonly Uri _uri;
private readonly Sex _sex;
ListItemViewData(Uri uri, Sex sex)
{
this._uri = uri;
this._sex = sex;
}
public BitmapSource Image
{
get
{
// Do synchronous WebRequest
}
}
}
Использование в xaml (внутри DataTemplate элемента списка):
<Image Source="{Binding Path=Image, IsAsync=True}"/>
EDITED
Я нырнул в класс BitmapImage и обнаружил, что у него довольно ctor с параметром Uri, который работает асинхронно.
Таким образом, вы не должны выполнять WebRequest самостоятельно.Сделайте так:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var uri = (Uri)value;
return new BitmapImage(uri) { CacheOption = BitmapCacheOption.None };
}
EDITED 2
Ваш класс данных просмотра.
public class ListItemViewData : INotifyPropertyChanged
{
public ListItemViewData(Uri uri)
{
this._uri = uri;
}
private readonly Uri _uri;
public Uri Uri
{
get
{
return this._uri;
}
}
private BitmapSource _source = null;
public BitmapSource Image
{
get
{
return this._source;
}
set
{
this._source = value;
this.OnPropertyChanged("Image");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string p)
{
var pc = this.PropertyChanged;
if (pc!=null)
{
pc(this, new PropertyChangedEventArgs(p));
}
}
}
Помощник, который выполняет загрузку изображений:
public static class WebHelper
{
public static Stream DownloadImage(Uri uri, string savePath)
{
var request = WebRequest.Create(uri);
var response = request.GetResponse();
using (var stream = response.GetResponseStream())
{
Byte[] buffer = new Byte[response.ContentLength];
int offset = 0, actuallyRead = 0;
do
{
actuallyRead = stream.Read(buffer, offset, buffer.Length - offset);
offset += actuallyRead;
}
while (actuallyRead > 0);
File.WriteAllBytes(savePath, buffer);
return new MemoryStream(buffer);
}
}
}
Когда вы заполняете модель - вы должны запустить отдельный поток, который будет загружать файлы и настраивать источник изображений.
this._listItems.Add(new ListItemViewData(new Uri(@"http://lifeboat.com/images/blue.ocean.jpg")));
//...
var sc = SynchronizationContext.Current;
new Thread(() =>
{
foreach (var item in this._listItems)
{
var path = "c:\\folder\\"+item.Uri.Segments.Last();
var stream = WebHelper.DownloadImage(item.Uri, path);
sc.Send(p =>
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = (Stream)p;
bi.EndInit();
item.Image = bi;
}, stream);
}
}).Start();