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

时间:2015-12-08 17:37:23

标签: c# wpf xaml caching binding

我是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.

2 个答案:

答案 0 :(得分:1)

当您绑定到 CurrentImage 并且 CurrentImage 的值发生更改时,您必须为 CurrentImage 引发属性更改事件。

根据提供的代码,您也可以这样做:

public Uri currentImageNotifier
{
    get { return CurrentImage; }
    set
    {
        CurrentImage = value;
        RaisePropertyChanged("CurrentImage");
    }
}

答案 1 :(得分:1)

绑定到可观察集合时,您正在订阅集合中的更改(例如,在集合中添加或删除项目)。这不会订阅您对集合中各个项目的属性的更改。正如其他人所说,如果要绑定到项目上的属性,则需要在属性更改时引发PropertyChanged事件。

private Uri currentImage;

public Uri CurrentImage
{
    get { return currentImage; }
    set 
    { 
        currentImage = value;
        RaisePropertyChanged("CurrentImage");
    }
}

注意:您可能希望将setter包装在if语句中并使用Uri.Compare()来确定给定值是否实际上与当前值不同。这样,您只会在属性实际更改时引发PropertyChanged事件。

此外,在您的代码示例中,您要在此CurrentImage循环中设置foreach属性:

foreach(var comp in CompListObs) 
{ 
    comp.CurrentImage = ResourceHelper.LoadBitmapURIFromResource("another image");
}

但是,您要从PropertyChanged属性中提升currentImageNotifier事件。可以从正在修改的媒体资源之外的位置提升PropertyChanged个事件,但您需要使用{{1}替换CurrentImage循环中的foreach作业},或修改您的currentImageNotifier属性以提升自己的CurrentImage事件。就目前情况而言,您实际上并未在您绑定的属性上举起PropertyChanged事件。

老实说,看起来你甚至不需要PropertyChanged属性。它没有做任何你不能直接使用currentImageNotifier财产的事情。