使用数据绑定在WPF MVVM中以ListView(或更好的东西!)显示图像

我试图在ListView中显示一些图像,但没有成功。 我正在使用WPF MVVM,而ListView是简单地显示套装和排名数据的延续。 (请参阅我之前的post: WPF中的MVVM – 如何提醒ViewModel模型中的更改……或者我应该?如果您感兴趣的话!)也就是说,我可以使用ListView之外的其他东西(如果这是建议)但我仍然想知道如何使用ListView,假设它是可行的。 我在ViewModel中绑定的属性是:

public ObservableCollection PlayerCardImages{ get{ ObservableCollection results = new ObservableCollection(); foreach (CardModel card in PlayerCards) { Image img = new Image(); BitmapImage bi3 = new BitmapImage(); bi3.BeginInit(); // TODO: Pick card based on suit/rank. Just get 1 image working now bi3.UriSource = new Uri("diamond-1.png", UriKind.Relative); bi3.EndInit(); img.Stretch = Stretch.Fill; img.Source = bi3; results.Add(img); } return results; } } 

在我使用的XAML代码中:

          

这个想法被无耻地偷走了: WPF – 将图像水平绑定到ListView然而,它甚至看起来都没有数据绑定,因为我在PlayerCardImages中的断点未被击中。

我也尝试了以下XAML运气好一点:

    

这段代码肯定会通过数据绑定 – 我的断点在程序开始时以及项目添加到集合时被点击。 但是没有显示图像。 不要用更多不起作用的XAML折磨你,也许我可以请某人指出一些代码/示例/文档,它们展示如何将图像列表绑定到ListView(或者如果你真的觉得ListView是另一个控件的话)不当)。 请注意,我的collections是我绑定的东西。 我注意到,通过许多示例,它们绑定到子属性。 即他们可能有一组专辑,并且每张专辑都会绑定到它的属性图像(请参阅: 在WPF ListView中将项目显示为图像 )。

任何想法或帮助将不胜感激。

戴夫

附加信息。

根据Clemens的建议,我现在有了PlayerCardImages的代码:

 public ObservableCollection PlayerCardImages { get { var results = new ObservableCollection(); //if (PlayerCards.Count == 0) // return results; //else //{ // results.Add(new BitmapImage(new Uri(@"Images\\" + "diamond-1.png", UriKind.Relative))); //} foreach (var card in PlayerCards) { results.Add(new BitmapImage(new Uri(@"Images\\" + GetCardFileName(card), UriKind.Relative))); } return results; } 

我使用了他建议的确切XAML。 它几乎可以工作。 我说“差不多”因为我注意到奇怪的行为,有时一张卡会显示,有时不会(我从来没有2张卡)。 从文件和绑定中获取的所有卡片似乎都在工作,我跟踪了我认为最后剩下的bug(它是BIZARRE)的关键。 如果在调试器中,我检查结果,并在调试器中进一步打开结果[0],我会显示该卡! 我实际上必须打开[0](你看到有关高度,宽度等的信息)才能使用。 此外,如果我打开[1],我会显示该卡。 为什么打开调试器信息有什么影响? 对于那些可能会问的人,如果你在调试器中打开这两张卡会发生什么……那是行不通的。 我得到一个操作超时exception。 我会说,也许我的图像文件很大。 10Kbytes到30Kbytes。 这是问题吗? 我猜不是,这是读取图像或装订时的一个微妙问题。 到底是怎么回事? 谢谢,戴夫

首先,您不应在ViewModel中使用Image控件。 您已在视图的DateTemplate中拥有Image控件。 您想绑定此Image conntrol的Source属性,并且此绑定的source属性不能是另一个Image。

相反,您的ViewModel将使用ImageSource (或类似BitmapImage的派生类)作为图像类型,如下所示:

 public ObservableCollection PlayerCardImages { get { var results = new ObservableCollection(); foreach (var card in PlayerCards) { results.Add(new BitmapImage(new Uri(card.ImageUrl))); } return results; } } 

或者只是图像URI或路径,因为从string自动转换为内置到WPF中的ImageSource

 public ObservableCollection PlayerCardImages { get { var results = new ObservableCollection(); foreach (var card in PlayerCards) { results.Add(card.ImageUrl); } return results; } } 

您现在将Listbox的ItemsSource属性绑定到PlayerCardGames集合,并在DataTemplate中直接绑定到集合项。 必须将ListView的DataContext设置为定义PlayerCardGames属性的对象的实例。

          

更新:由于加载图像文件似乎有问题,您可以尝试以下方法。 它同步加载图像,您可以使用调试器。

 public static ImageSource LoadImage(string fileName) { var image = new BitmapImage(); using (var stream = new FileStream(fileName, FileMode.Open)) { image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; image.StreamSource = stream; image.EndInit(); } return image; } 

你可以在你的PlayerCardGames属性getter中使用这个方法,如下所示:

 foreach (var card in PlayerCards) { results.Add(LoadImage(@"Images\\" + GetCardFileName(card))); } 

我并没有真正尝试重现你的问题,但如果不能解决问题,我会这样做:

在你的第一个xaml块中,我认为你混淆了绑定。 这将是我期待它,ItemsSource到图像的ObservableCollection,Image的图像源。

   

在第二个块中,您完全省略了Source绑定: