我有一个ListView,在datatamplate中有一个Image和一些TextBlock。这些控件绑定来自集合对象的信息,但图像控件的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?)。我的问题是,是否有一种方法可以从文件中检索数据,用于图像控制以避免死锁?
panda是对的,你真的不应该在转换器中打开这个文件。这样,每次调用Convert()时,都会打开文件并从中读取,这会占用太多不必要的时间和资源。更不用说它挂起了UI线程并导致死锁。您应该在填充ListView之前或期间打开该文件,从中读取URL列表,然后绑定到(可观察的)集合。
如果你想坚持你目前的解决方案(我强烈建议你不要这样做),请阅读这里的公认答案,克利里先生完美而深入地描述了这个问题。
我就是这么做的:你需要让PlayerHistory成为一个项目的ObservableCollection,这样当添加新项目或从中删除旧项目时,ListView就会收到通知。根据你的代码片段,我想你已经这样做了。您需要的第二件事是,您必须使PlayerHistory中的项(现在我们称它们为HistoryViewModel)实现INotfyPropertyChanged接口,它们必须有一个属性(我们称之为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 x:DataType="data:HistoryViewModel ">
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Image Source="{Binding PictureUri}" /> ...
这样,每当您更新支持ViewModels的PictureUri属性时,由于数据绑定,ListView的项也会自动更新。