从列表更新 WPF 图像

Update WPF Images from a list

我在一张 window 中有 40 张图片需要更改。我认为检查这 40 张图像中的任何一张是否需要在计时器上更改的最简单方法是将它们放入 List<ImgInfo>,其中 ImgInfo 包含 System.Windows.Controls.Image

我的代码会更新列表,但不会更改 Window 上的当前图像。

我对在 WPF 中处理图像还很陌生。 我应该将这些图像绑定到代码中的 属性 吗?现在 xaml 只是将源设置为单个图像。将这些图像绑定到列表中的项目需要什么?

// xaml:
 <Image x:Name="comp01" Height="75" Source="img/comp-offline.png" Stretch="Fill" Margin="5"/>

// When the application starts:
ImgInfoList= new List<ImgInfo>();
ImgInfoList.Add(new ImgInfo{ CurrentImage = comp01, MachineName = "" });
ImgInfoList.Add(new ImgInfo{ CurrentImage = comp02, MachineName = "" });
// ... etc for 40 images

// ImgInfo class:
public class ImgInfo
{
    public string MachineName { get; set; }
    public Image CurrentImage { get; set; }
}

public void MainTimer_Tick(object sender, EventArgs e)
{
    foreach(var imgInfo in ImageInfoList)
    {
        if(//conditions are true) 
        {
            Image imgTmp = new Image();
            BitmapImage bi3 = new BitmapImage();
            bi3.BeginInit();
            bi3.UriSource = new Uri(LoadBitmapURIFromResource("img/img-1.png"));
            bi3.EndInit();
            imgTmp.Stretch = Stretch.Fill;
            imgTmp.Source = bi3;
            imgInfo.CurrentImage = imgTmp;
        }
        // else if... img/img-2.png, etc.
    }
}

//LoadBitmapURIFromResource just returns Convert.ToString(new Uri(@"pack://application:,,,/" + assembly.GetName().Name + ";component/" + pathInApplication, UriKind.Absolute));

要在 WPF 中处理多个图像,您应该为图像使用 ObservableCollection(仅包含文件名)并将其用作 ListBox 的 ItemsSource。 ItemTemplate 将是您的图像,它绑定到文件名。

    <ListBox ItemsSource="{Binding ImgList}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Image Source="{Binding}" ... />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

ImgList 必须是您的 DataContext 中的 属性。 如果您需要 ListBox 的不同布局,您可以更改 ListBox 的 ItemsPanel。

要更改图像,只需替换字符串即可。请注意,默认情况下图像组件会缓存图像。如果要从同一文件重新加载图像,则必须禁用缓存。

编辑:

正如所承诺的那样,我想展示如何使用绑定在 <Canvas/> 上的特定位置显示图像。首先,我们需要修改你的ImgInfoclass。它现在包含要显示的图像的路径、位置和大小:

public class ImgInfo
{
    public string Path { get; set; }
    public double X { get; set; }
    public double Y { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
}

<ListBox/> 将按以下方式扩展:

    <ListBox ItemsSource="{Binding ImgList}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Image Source="{Binding Path}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
                <Setter Property="Canvas.Left" Value="{Binding X}"/>
                <Setter Property="Canvas.Top" Value="{Binding Y}"/>
                <Setter Property="Width" Value="{Binding Width}"/>
                <Setter Property="Height" Value="{Binding Height}"/>
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>

作为ItemsPanel,我们使用了一个<Canvas/>元素。为了确保项目显示在特定位置,我们修改 ItemContainerStyle 以将相应的属性绑定到我们的 ImgInfo 实例。

现在您可以在 ImgList 中添加新项目或替换它们,所做的更改将反映在 <ListBox/> 中。如果你想直接修改ImgInfo-Items,你将不得不在这个class.

中实现INotifyPropertyChanged