在WPF值转换器中异步加载图像

sco*_*ott 0 c# wpf

我有一个WPF列表框,它将绑定大量图像.每个图像可能来自本地磁盘或从Exe本身获取图标.

我将所有这些解析代码放在MultiValueConverter中.但它现在似乎阻止了UI.如何使该异步?

代码示例:https://github.com/qianlifeng/Wox/blob/master/Wox/Converters/ImagePathConverter.cs#L53

pus*_*raj 7

你可以利用的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.