正在将图像绑定到wpf中的嵌入资源
本文关键字:wpf 嵌入资源 绑定 图像 | 更新日期: 2023-09-27 18:26:06
我是WPF的新手,遇到了一个问题。我有一个ListBox,其中的图像排列在平面图中,图像源绑定到代码中的uri。uri是指项目中的嵌入资源。这一切在启动时都很好,直到我不得不更改图像。没有例外,但图像不会改变。当我在调试中运行时,我可以看到即使ObservableCollection项发生了更改,主窗口映像也不会发生更改。
这是由于缓存,还是其他原因?我试图禁用xaml中的缓存,但我得到了错误The TypeConverter for "CacheMode" does not support converting from a string.
我会尽我所能简要介绍代码,只包括相关信息:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public ObservableCollection<ComputerInfo> CompListObs;
public ObservableCollection<ComputerInfo> compListObsNotifier
{
get { return CompListObs; }
set
{
CompListObs = value;
RaisePropertyChanged("compListObsNotifier");
}
}
//...
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
// This correctly loads the images from the xml and displays them on the main window:
var items = XDocument.Load(@"path to xml")
.Descendants("Computer")
.Select(i => new ComputerInfo {
MachineName = (string)i.Element("MachineName"),
Lat = (double)i.Element("Long"),
Lon = (double)i.Element("Lat"),
CurrentImage = ResourceHelper.LoadBitmapURIFromResource((string)i.Element("Img"))
}).ToList();
CompListObs = new ObservableCollection<ComputerInfo>(items);
}
public void MainTimer_Tick(object sender, EventArgs e)
{
// This runs fine and I can see the members of CompListObs are changing,
// but the images on the mainwindow are not changing.
foreach(var comp in CompListObs) { comp.CurrentImage = ResourceHelper.LoadBitmapURIFromResource("another image");
}
// INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void RaisePropertyChanged(string propName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public class ComputerInfo : INotifyPropertyChanged
{
public ClientInfo ClientsInfo { get; set; }
public string MachineName { get; set; }
public Uri CurrentImage { set; get; }
public double Lat { get; set; }
public double Lon { get; set; }
public Uri currentImageNotifier
{
get { return CurrentImage; }
set
{
CurrentImage = value;
RaisePropertyChanged("compListObsNotifier");
}
}
// INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public void RaisePropertyChanged(string propName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
这是xaml:
<ListBox ItemsSource="{Binding compListObsNotifier}">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Path=CurrentImage}" Height="65"></Image>
</DataTemplate>
</ListBox.ItemTemplate>
<!-- after this, I place <ListBox.ItemsPanel> <ItemsPanelTemplate> and <Canvas> in the ListBox.
当您绑定到可观察集合时,您正在订阅集合中的更改(例如,添加或删除集合中的项)。这不会为您订阅对集合中单个项目属性的更改。正如其他人所说,如果要绑定到项的属性,则需要在属性更改时引发PropertyChanged
事件。
private Uri currentImage;
public Uri CurrentImage
{
get { return currentImage; }
set
{
currentImage = value;
RaisePropertyChanged("CurrentImage");
}
}
注意:您可能希望将setter封装在if
语句中,并使用Uri.Compare()
来确定给定值是否与当前值实际不同。这样,只有在属性实际更改时才会引发PropertyChanged
事件。
此外,在您的代码示例中,您正在foreach
循环中设置CurrentImage
属性:
foreach(var comp in CompListObs)
{
comp.CurrentImage = ResourceHelper.LoadBitmapURIFromResource("another image");
}
但是,您正在从currentImageNotifier
属性引发PropertyChanged
事件。从正在修改的属性之外的位置引发PropertyChanged
事件是可以的,但您需要用currentImageNotifier
替换foreach
循环中的CurrentImage
赋值,或者修改CurrentImage
属性以引发自己的PropertyChanged
事件。目前,您实际上并没有在绑定到的属性上引发PropertyChanged
事件。
老实说,看起来你甚至不需要currentImageNotifier
属性。它没有做任何你不能直接用CurrentImage
属性做的事情。
当您绑定到CurrentImage并且urrentImageurrentImage属性更改事件。
根据提供的代码,您也可以这样做:
public Uri currentImageNotifier
{
get { return CurrentImage; }
set
{
CurrentImage = value;
RaisePropertyChanged("CurrentImage");
}
}