正在将图像绑定到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.

正在将图像绑定到wpf中的嵌入资源

当您绑定到可观察集合时,您正在订阅集合中的更改(例如,添加或删除集合中的项)。这不会为您订阅对集合中单个项目属性的更改。正如其他人所说,如果要绑定到项的属性,则需要在属性更改时引发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");
    }
}