【问题标题】:How to update WPF image.Source on value change in separate static class如何更新 WPF image.Source 在单独的静态类中的值更改
【发布时间】:2016-10-20 15:22:06
【问题描述】:

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

我只是不知道如何使bitmapSource的变化导致图像控件的更新。这通常是怎么做的?我阅读了有关 Propertychangedevents 的信息,但不知道如何在这种情况下实现它们。
在我之前的 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
    }
}

【问题讨论】:

    标签: c# wpf data-binding camera


    【解决方案1】:

    正如您所说的您想了解 WPF,查看INotifyPropertyChanged 不会做错任何事情。如果您甚至在这里搜索堆栈溢出的示例,那将为您提供一个温和的介绍。

    这样,您通常会将您的 XAML 图像数据绑定到图像源,类似于

    <Image Source="{Binding CurrentCameraImage}" />
    

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

    为了避免静态类,您可以将CameraClass 变成Singleton

    这有意义吗?如果数据绑定方法不是您所擅长的(例如,您需要了解 BindingContext 是什么),请查看如何包含 events:您的相机类将定义一个事件,而您的主类将订阅它。然后,该事件将向您的主类发出可用更新的信号,并允许您从相机更新 UI 上的图片。

    【讨论】:

    • 尝试 INotifyPropertyChanged 是我做的第一件事。但是将它应用于静态类会给我一个错误,说“静态类不能实现接口”。
    • 好吧,在这种情况下,也许你可以选择单身人士。
    【解决方案2】:

    WPF 应用程序通常实现 MVVM 模式,其中视图元素绑定到视图模型中的属性。在最简单的情况下,只有一个视图模型类的实例被分配给应用程序 MainWindow 的 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}"/>
    

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

    【讨论】:

    • 但这实际上并不是关于如何使用静态类来做到这一点的答案?
    • 不,但它显示了您应该如何真正做到这一点。在 StackOverflow 上,答案通常超出问题的详细信息,以便向提问者(以及其他出现的人)展示一般是如何解决问题的。
    • 这个问题非常具体,因为一般解决方案不起作用。您的回答只是对文档的重写,并没有回答实际问题。我很感谢您的回复,但由于无法解决问题,因此无法正式接受。在我的项目中,我现在省略了静态类 - 但只是因为我找不到任何其他方式,而不是因为我想:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-29
    • 1970-01-01
    • 2012-03-18
    • 2016-03-27
    相关资源
    最近更新 更多