我有一个WPF列表框,它将绑定大量图像.每个图像可能来自本地磁盘或从Exe本身获取图标.
我将所有这些解析代码放在MultiValueConverter中.但它现在似乎阻止了UI.如何使该异步?
代码示例:https://github.com/qianlifeng/Wox/blob/master/Wox/Converters/ImagePathConverter.cs#L53
你可以利用的IsAsync财产Binding
来自MSDN:
当绑定源属性的get访问器可能需要很长时间时,请使用IsAsync属性.一个示例是具有从Web下载的get访问器的图像属性.将IsAsync设置为true可避免在下载时阻止UI.
例
<Image Source="{Binding MyImage,IsAsync=True, Converter={StaticResource MyConverter}}" />
Run Code Online (Sandbox Code Playgroud)
更多关于Binding.IsAsync
异步转换器
我设法创建了一个异步转换器
namespace CSharpWPF
{
class AsyncConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return new AsyncTask(() =>
{
Thread.Sleep(4000); //long running job eg. download image.
return "success";
});
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
public class AsyncTask : INotifyPropertyChanged
{
public AsyncTask(Func<object> valueFunc)
{
AsyncValue = "loading async value"; //temp value for demo
LoadValue(valueFunc);
}
private async Task LoadValue(Func<object> valueFunc)
{
AsyncValue = await Task<object>.Run(()=>
{
return valueFunc();
});
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("AsyncValue"));
}
public event PropertyChangedEventHandler PropertyChanged;
public object AsyncValue { get; set; }
}
}
}
Run Code Online (Sandbox Code Playgroud)
此转换器将返回一个实例,AsyncTask该实例将封装长时间运行的作业
class AsyncTask将异步执行任务,并将结果设置为, AsyncValue因为它也实现,INotifyPropertyChanged因此使用通知来更新UI
用法
<Grid xmlns:l="clr-namespace:CSharpWPF">
<Grid.Resources>
<l:AsyncConverter x:Key="AsyncConverter" />
</Grid.Resources>
<TextBlock DataContext="{Binding MyProperty,Converter={StaticResource AsyncConverter}}"
Text="{Binding AsyncValue}" />
</Grid>
Run Code Online (Sandbox Code Playgroud)
想法是将DataContext元素绑定到转换器,并将所需属性绑定到新数据上下文的AsyncValue
以上示例使用文本块的Text属性进行简单演示
例如,IValueConverter也可以使用相同的方法IMultiValueConverter.