Если вы можете получить данные изображения в массиве байтов, то вы можете напрямую привязать свойство Source элемента управления Image к этому свойству без необходимости в каком-либо преобразователе.
public class UserModel
{
public Guid? Id { get; set; }
public string Name { get; set; }
public byte[] ProfileImage { get; set; }
}
<ListBox ItemsSource="{Binding UserModelCollection}">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:UserModel}">
<Grid
Height="32"
Margin="4"
Focusable="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
VerticalAlignment="Center"
Source="{Binding ProfileImage}"
Stretch="Uniform" />
<TextBlock
Grid.Column="2"
VerticalAlignment="Center"
Text="{Binding Name}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Чтобы избежать блокировки Поток пользовательского интерфейса, особенно если у вас большой список пользователей и вы хотите получать изображения только по запросу, когда этот элемент отображается, я предлагаю использовать асинхронное свойство.
/// <summary>
/// A read only property where the value is fetched once when required, in an async manner, and then cached for future use.
/// </summary>
/// <remarks>
/// in Xaml, bind to perAsyncPropertyInstance.Value
/// </remarks>
/// <typeparam name="T"></typeparam>
public class perAsyncProperty<T> : perViewModelBase where T : class
{
private readonly Func<Task<T>> _fetchValue;
public perAsyncProperty(Func<Task<T>> fetchValue)
{
_fetchValue = fetchValue;
}
private bool _fetchingValue;
private T _value;
/// <summary>
/// The property's value - use this as the source of data binding.
/// </summary>
public T Value
{
get
{
if (_value != null || _fetchingValue)
{
return _value;
}
_fetchingValue = true;
// can't use await inside a property getter, so use a continuation instead
_fetchValue()
.EvaluateFunctionWithTimeoutAsync(FetchValueTimeOut)
.ContinueWith(FetchValueContinuation);
// Local function to refresh Value once the data fetch task has completed
async void FetchValueContinuation(Task<perAsyncFunctionResponse<T>> task)
{
var taskResult = await task.ConfigureAwait(false);
if (taskResult.IsCompletedOk)
{
Value = taskResult.Data;
}
else if (taskResult.IsTimedOut)
{
OnTimeOutAction?.Invoke(taskResult);
}
else if (taskResult.IsError)
{
OnErrorAction?.Invoke(taskResult);
}
_fetchingValue = false;
}
return _value;
}
private set => Set(nameof(Value), ref _value, value);
}
/// <summary>
/// Timeout value for FetchValue invocation
/// </summary>
public TimeSpan FetchValueTimeOut { get; set; } = perTimeSpanHelper.Forever;
/// <summary>
/// Optional action to perform if FetchValue generates an error.
/// </summary>
public Action<perAsyncFunctionResponse<T>> OnErrorAction { get; set; }
/// <summary>
/// Optional action to perform if FetchValue times out.
/// </summary>
public Action<perAsyncFunctionResponse<T>> OnTimeOutAction { get; set; }
/// <summary>
/// Clear Value and force it to be re-fetched then next time it is read.
/// </summary>
public void ResetValue()
{
_fetchingValue = false;
Value = null;
}
}
public class perBytesFromFileAsyncProperty : perAsyncProperty<byte[]>
{
public perBytesFromFileAsyncProperty(string filePath) : base(() => FetchData(filePath))
{
}
private static Task<byte[]> FetchData(string filePath)
{
Debug.WriteLine("loading file - " + filePath);
return perIOAsync.ReadAllBytesFromFileRawAsync(filePath);
}
}
public class perBytesFromUrlAsyncProperty : perAsyncProperty<byte[]>
{
public perBytesFromUrlAsyncProperty(string url): base(() => FetchData(url))
{
}
private static Task<byte[]> FetchData(string url)
{
Debug.WriteLine("downloading Url - " + url);
return perIOAsync.ReadAllBytesFromUrlRawAsync(url);
}
}
Используйте соответствующий версия в зависимости от того, является ли ваша строка для источника изображения путем к файлу или веб-URL.
Теперь UserModel и привязка представления могут быть закодированы как
public class UserModel
{
public UserModel (Guid id, string name, string imageFilePath)
{
Id = id;
Name = name;
ProfileImage = new perBytesFromFileAsyncProperty(imageFilePath);
}
public Guid? Id { get; set; }
public string Name { get; set; }
public perBytesFromFileAsyncProperty ProfileImage { get; set; }
}
<ListBox ItemsSource="{Binding UserModelCollection}">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:UserModel}">
<Grid
Height="32"
Margin="4"
Focusable="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
VerticalAlignment="Center"
Source="{Binding ProfileImage.Value}"
Stretch="Uniform" />
<TextBlock
Grid.Column="2"
VerticalAlignment="Center"
Text="{Binding Name}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Подробнее о моем сообщение в блоге .