C# WPF中设置绑定时,INotifyPropertyChanged接口如何对数组使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# WPF中设置绑定时,INotifyPropertyChanged接口如何对数组使用相关的知识,希望对你有一定的参考价值。

比如说:
public class A: INotifyPropertyChanged

private string[] m_S = new string[3];

public string[] S

get return m_S;
set

m_S = value;
if (PropertyChanged != null)
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("S"));


public event PropertyChangedEventHandler PropertyChanged;


后台代码:
A a = new A();
Label1.SetBinding(Label.ContentProperty, new Binding("S") Source = a);
Label2.SetBinding(Label.ContentProperty, new Binding("S") Source = a);
Label3.SetBinding(Label.ContentProperty, new Binding("S") Source = a);

实际上我需要Label1的内容与S[0]绑定,Label2的内容与S[1]绑定,Label3的内容与S[2]绑定,属性S和m_S数组也是一一对应的,上述代码应该如何修改才能实现呢

参考技术A 如果你这些类继承自同一个根基类的话那么只用在根基类实现该接口就行了啊追问

总共只有一个类

使用 WPF、Caliburn 和 C# 从图像转换为图像源

【中文标题】使用 WPF、Caliburn 和 C# 从图像转换为图像源【英文标题】:Converting from Image to Imagesource using WPF, Caliburn and C# 【发布时间】:2022-01-18 05:51:48 【问题描述】:

我正在尝试在 WPF 中设置网络摄像头流。我有一个项目正在运行,其中所有内容都是代码。但是,我很想让它更干净并将其转换为 MVVM。 我的问题是,我无法将流中的图像绑定到视图,并得到以下错误:

绑定路径 Cameraimage, Taget Image.Source, Target Type ImageSource 不带点

无法从“System.Windows.Controls.Image”类型转换为“System.Windows.Media.ImageSource”。考虑在绑定上设置转换器。

这部分程序的主要处理是 View.xaml ViewModel.cs 和一个实用程序 CameraStreaming.cs -(很明显称为视图和视图模型以外的其他名称,但我试图保持简单)

View.xaml-sn-p

    <Border
        x:Name="webcamContainer"
        Grid.Column="0"
        Grid.Row="3"
        BorderBrush="Black"
        BorderThickness="1">

        <Image Source="Binding CameraImage"  VerticalAlignment="Top" />
        
    </Border>

ViewModel.cs-sn-p

private Image _cameraImage;

    public Image CameraImage
    
        get  return _cameraImage; 
        set  _cameraImage = value;
            NotifyOfPropertyChange(() => CameraImage);
    
(....)
    var selectedCameraDeviceId = SelectedCamera.OpenCvId;

            if (_camera == null || _camera.CameraDeviceId != selectedCameraDeviceId)
            
                _camera?.Dispose();
                
                _camera = new CameraStreaming(

                    imageControlForRendering: CameraImage, // See my CameraStreaming utility
                    cameraDeviceId: SelectedCamera.OpenCvId);
                
            

            try
            
                await _camera.StartCamera(true);
               // await _ultraSound.Start(false);

            

CameraStreaming.cs-sn-p

private readonly Image _imageControlForRendering;

public CameraStreaming(Image imageControlForRendering, int cameraDeviceId)
    
        _imageControlForRendering = imageControlForRendering;
        CameraDeviceId = cameraDeviceId;

    
 public async Task StartCamera(bool crop)
    
        
        if (_previewTask != null && !_previewTask.IsCompleted)
            return;

        var initializationSemaphore = new SemaphoreSlim(0, 1);

        _cancellationTokenSource = new CancellationTokenSource();
        _previewTask = Task.Run(async () =>
        
            try
            
               var videoCapture = new VideoCapture();

                if (!videoCapture.Open(CameraDeviceId))
                
                    throw new ApplicationException("Cannot connect to camera");
                

                using (var frame = new Mat())
                
                    while (!_cancellationTokenSource.IsCancellationRequested)
                    
                        videoCapture.Read(frame);

                        if (!frame.Empty())
                        
                            // Releases the lock on first not empty frame
                            if (initializationSemaphore != null)
                                initializationSemaphore.Release();


                            // _lastFrame = BitmapConverter.ToBitmap(frame);


                                _lastFrame = BitmapConverter.ToBitmap(frame.Flip(FlipMode.Y));

                            var lastFrameBitmapImage = _lastFrame.ToBitmapSource();
                            lastFrameBitmapImage.Freeze();
                            _imageControlForRendering.Dispatcher.Invoke(
                                () => _imageControlForRendering.Source = lastFrameBitmapImage);
                        

                        
                        await Task.Delay(10);
                    
                

                videoCapture?.Dispose();
            
            finally
            
                if (initializationSemaphore != null)
                    initializationSemaphore.Release();
            

        , _cancellationTokenSource.Token);


        await initializationSemaphore.WaitAsync();
        initializationSemaphore.Dispose();
        initializationSemaphore = null;

        if (_previewTask.IsFaulted)
        
            // To let the exceptions exit
            await _previewTask;
        
    

所以.. 我迷路了。由于log4j问题,目前大部分官方文档都被关闭了,我想我看了这么久可能已经失明了:P

【问题讨论】:

看来您可以通过将lastFrameBitmapImage 设置为 ViewModel 的属性并将其与 View 中的图像绑定来解决此问题。 【参考方案1】:

您不能在视图模型中使用System.Windows.Controls.Image 作为图像属性的类型,原因有二。

    这是一个UIElement,因此不属于视图模型 不能分配给视图中另一个图像元素的Source属性

将类型改为ImageSource

private ImageSource _cameraImage;

public ImageSource CameraImage

    get  return _cameraImage; 
    set
    
        _cameraImage = value;
        NotifyOfPropertyChange(() => CameraImage);
    

并使用新的相机框架更新视图模型:

var lastFrameBitmapSource = _lastFrame.ToBitmapSource();
lastFrameBitmapSource.Freeze();

viewModel.CameraImage = lastFrameBitmapSource;

如果您不想将视图模型的引用传递给辅助类,则需要另一种通知机制。

【讨论】:

谢谢!这解决了 Image vs Imagesource 问题!但是,绑定似乎不起作用。相机打开,我可以看到,数据在我的本地人中设置正确。但是,它没有显示。我尝试了 Source="Binding CameraImage" 和 x:Name="CameraImage" (我正在使用 Caliburn),但都不起作用。你知道为什么吗? 您的问题并不清楚,但为了使Source="Binding CameraImage" 工作,您必须将视图模型实例分配给视图的 DataContext 属性,例如主窗口。 我已将其作为一个新问题提出。由于我使用的是 Caliburn,因此数据上下文是自动设置的。但是,我也尝试在后面的代码中设置它,这并没有改变任何东西。 ***.com/questions/70387364/…

以上是关于C# WPF中设置绑定时,INotifyPropertyChanged接口如何对数组使用的主要内容,如果未能解决你的问题,请参考以下文章

TextBlock在wpf C#中的图像内的特定坐标中设置

如何在 WPF 中设置 DataGrid 的 DataSource?

在 XAML 中设置 WPF OxyPlot PlotViews 的样式

使用 WPF、Caliburn 和 C# 从图像转换为图像源

数据绑定到 WPF 中的 UserControl

WPF - 为啥在 XAML 中设置 Binding BindableObject.Text 时 SetProperty() 不触发 CanExecute?