如何更新WPF图像.源代码在单独的静态类的值变化

本文关键字:单独 静态类 变化 源代码 图像 何更新 更新 WPF | 更新日期: 2023-09-27 18:13:56

我最近从Forms转到了WPF,以获得一些新的专业知识。首先,我想编写一个相机应用程序。相机在它自己的静态类中被访问(因为我只有一个相机-所以不需要多个实例)。UI应该通过图像控件在实时视图中显示当前图像。camera类在无限循环中更新BitmapSource,然后我想将其用作图像控件的源。

我只是不知道如何使bitmapSource的变化导致图像控件的更新。这通常是怎么做的?我读过propertychangeevent,但不知道如何在这种情况下实现它们。
在之前的Forms应用程序中,我有一个计时器,每秒更新表单30次,并使用公共位图作为图片框控件的源。但这是一种丑陋的方式,我想做得更好。

代码如下:相机类

static class CameraClass
{
    static Camera myCam = new Camera(); //from API
    public static BitmapSource CurrentCameraImage;
    private static void GetCameraImages()
    {
       while(true)
       {
           myCam.GetImage(out CurrentCameraImage, 1000); //from API
       }
    }
    public static void StartCamera()
    {
        myCam.StartAcquisition(); //from API
        Task.Run(() => { GetCameraImages(); });
    }
}

标准WPF类

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        CameraClass.StartCamera(); 
        //this should now cause the image control to update 
        //everytime the bitmapsource is changed
    }
}

如何更新WPF图像.源代码在单独的静态类的值变化

WPF应用程序通常实现MVVM模式,其中视图元素绑定到视图模型中的属性。在最简单的情况下,只有一个视图模型类的实例,它被分配给应用程序的主窗口的DataContext属性。

你的视图模型类看起来像这样:

class CameraViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private Camera camera = new Camera();
    private BitmapSource currentCameraImage;
    public BitmapSource CurrentCameraImage
    {
        get { return currentCameraImage; }
        set
        {
            currentCameraImage = value;
            PropertyChanged?.Invoke(
                this, new PropertyChangedEventArgs("CurrentCameraImage"));
        }
    }
    public async Task StartCamera()
    {
        await Task.Run(async () =>
        {
            while (true)
            {
                BitmapSource bitmap;
                camera.GetImage(out bitmap, 1000); // from API
                bitmap.Freeze(); // make bitmap cross-thread accessible
                CurrentCameraImage = bitmap;
            }
        });
    }
}

在MainWindow构造器中,您将创建视图模型的实例,并将其分配给DataContext属性,如下所示:

public MainWindow()
{
    InitializeComponent();
    var viewModel = new CameraViewModel();
    viewModel.StartCamera();
    DataContext = viewModel;
}
最后,在XAML中将有一个Image元素绑定到视图模型的CurrentCameraImage属性:
<Image Source="{Binding CurrentCameraImage}"/>

在视图模型的改进实现中,应该在异步方法中等待Task。

正如您所说,您想了解WPF,通过查看INotifyPropertyChanged,您不会做任何错误的事情。如果你在这里搜索样本,甚至在堆栈溢出,这将给你一个温和的介绍。

使用

,你通常会用类似于

的东西将XAML图像数据绑定到图像源
<Image Source="{Binding CurrentCameraImage}" />

上面的代码只是一个指示,我现在不在电脑前。

为了避免静态类,你可以把CameraClass变成Singleton

明白了吗?如果数据绑定方法不是你想要的(例如,你需要学习什么是BindingContext),那么看看如何包含event s:你的相机类将定义一个事件,你的主类将订阅它。然后,该事件将向您的主类发出更新可用的信号,并允许您从相机更新UI上的图片。