x:使用异步方法绑定转换器

时间:2016-01-11 23:15:03

标签: c# uwp xbind

我有一个带有图像的ListView和一个带有datatamplate的TextBlocks。这些控件绑定来自集合对象的信息,但用于图像控制的URL位于文件上。我试图绑定一个字符串(这是文件的名称)并创建一个转换来检索该URL。

XAML:

<ListView Name="list" ItemsSource="{x:Bind Player.PlayerHistory, Mode=OneWay}">
        <ListView.ItemTemplate>
            <DataTemplate  x:DataType="data:HistoricoPartidas">
                <Grid HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch">
                     <Image Source="{x:Bind name, Converter={StaticResource ResourceKey=ItemConvert} }" />...

转换器:

class ItemConvert: IValueConverter {
    public object Convert(object value, Type targetType, object parameter, string language) {
        string s = value.ToString(); //value is binding  from an object of a collection
        ControlFile controle = new ControlFile();//class with file handler
        Character ch = controle.get(s).Result;//return a Character from file "s"
        return ch.Icon_URL;
}

我创建了上面的代码,但它导致了死锁(.Result?)。 我的问题是,是否有办法从文件中检索数据,在图像控制中使用避免死锁?

1 个答案:

答案 0 :(得分:1)

panda是对的,你真的不应该在转换器中打开文件。这样,每次调用Convert()时,您都会打开文件并从中读取,这会花费太多时间和资源。更不用说它挂起你的UI线程并导致死锁。您应该在填充ListView之前或期间打开文件,从中读取URL列表并绑定到该(可观察的)集合。

如果您想坚持使用当前的解决方案(我强烈建议您反对),请阅读the accepted answer here,Cleary先生完整而深入地描述了这个问题。

我将如何做到这一点:你需要让PlayerHistory成为一个ObservableCollection项,这样ListView会在添加新项目或从中删除旧项目时收到通知。根据您的代码段,我想您已经这样做了。你需要做的第二件事是你必须在PlayerHistory中创建项目(现在让他们称之为HistoryViewModel)实现INotfyPropertyChanged interface,他们必须拥有一个属性(让&#39; s称之为PictureUri),它将绑定到DataTemplate中,并且必须在此属性的setter中引发PropertyChanged事件。 这些用代码编写:

class HistoryViewModel : INotifyPropertyChanged
{
    private Uri _pictureUri;

    public Uri PictureUri
    {
        get
        {
            return _pictureUri;
        }
        set
        {
            if (value == _pictureUri)
                return;

            _pictureUri = value;

            RaisePropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

然后您的DataTemplate将如下所示:

 <DataTemplate x:DataType="data:HistoryViewModel ">
            <Grid HorizontalAlignment="Stretch"
                  VerticalAlignment="Stretch">
                 <Image Source="{Binding PictureUri}" /> ...

这样,每当您更新支持ViewModels的PictureUri属性时,由于数据绑定,ListView的项目也会自动更新。