MVVM 架构 WPF

Posted

技术标签:

【中文标题】MVVM 架构 WPF【英文标题】:MVVM architecture WPF 【发布时间】:2016-06-29 04:39:48 【问题描述】:

我对 WPF 中的 MVVM 有一点架构问题。我有View,其中包含编写一些代码或使用computers camera. If user choose to not scan the code, I can bindCommand 扫描QRCode 的选项,没有问题。

用户选择扫描二维码时出现问题。 当用户按下扫描代码时,屏幕的一部分被折叠并且相机显示在屏幕上。我必须在 View 后面的代码中执行此操作,所以我在 View 中得到的代码在 MVVM 中不好。

View 的代码如下所示:

private void Scan_Click(object sender, RoutedEventArgs e)
        
            if (_finalVideo.IsRunning)
            
                _finalVideo.Stop();
            

            _finalVideo = new VideoCaptureDevice(_cameraDevices[CamerasList.SelectedIndex].MonikerString);

            _finalVideo.NewFrame += (s, a) =>
            
                try
                
                    System.Drawing.Image img = (Bitmap)a.Frame.Clone();
                    var ms = new MemoryStream();
                    img.Save(ms, ImageFormat.Bmp);
                    ms.Seek(0, SeekOrigin.Begin);
                    var bitmapImage = new BitmapImage();
                    bitmapImage.BeginInit();
                    bitmapImage.StreamSource = ms;
                    bitmapImage.EndInit();
                    bitmapImage.Freeze();
                    Dispatcher.BeginInvoke(new ThreadStart(() =>
                    
                        CameraStream.Source = bitmapImage;
                        ReadQrCode(bitmapImage);
                    ));
                
                catch
                
                    //exc
                
            ;

            _finalVideo.Start();
        

我如何用MVVM 解决这个问题?

【问题讨论】:

是什么让您认为在视图中隐藏代码是不好的?如果它正在做与 UI 相关的工作,那么拥有这样的代码是完全可以的——这就是你正在做的事情。 我通常只是编写一个接口来抽象这些外部输入/输出的东西。因此,您最终会得到一个 ICommand Scan 属性,该属性在执行时会在接口上调用 Task<QrCode> ReadQrCodeFromCameraAsync 方法。在你的单元测试中,你做了这个接口的假实现。 【参考方案1】:

这很简单,只要您掌握了它并知道“用户控件”和视图之间的区别。

第一个声明是,理想情况下,后面的代码对于视图应该是空的。这是真实的。

但是,这不适用于用户控件。用户控件可以并且应该有代码,因为它们需要自我维持并且不将其逻辑提取到某些视图模型类中。

那么用户控件和视图之间有什么区别?是的,它们通常都派生自UserControl,但这不会使视图默认成为用户控件。重要的是,视图是为一个应用程序制作的非常特定的 UI 片段,不太可能在其他应用程序中重用。

例如,应用程序 A 中的 CustomerDetailViewCustomerDetailPage 将不同于应用程序 B 的同一视图,因为应用程序 B 可能对 CustomerDetailView 有不同的要求。

另一端的用户控件可以跨应用程序重复使用,例如DatePickerCalendarControlCameraControl。例如,此控件可用于可能需要相机的多个应用程序中。

这里重要的是,“用户控件”不知道您的应用程序结构,因此没有视图模型、业务/域模型等。如果您想允许 ViewModels 绑定到您的用户控件(ICommand for例如,启动和回调,或将生成的图片绑定到 ViewModel),然后将依赖项属性放入用户控件中。

当您在应用程序中使用此用户控件时,您只需将视图模型绑定到这些依赖属性 (DP),然后您就获得了抽象。

TL;DR: 视图中的代码不好,用户控件中的代码必要

【讨论】:

视图中的代码是完全可以的,只要它与演示相关。您对 Control 与 View 的区别很有用,但不要将其固定到特定的类。

以上是关于MVVM 架构 WPF的主要内容,如果未能解决你的问题,请参考以下文章

WPF MVVM WCF 客户端/服务器架构

分层企业应用程序中的 WPF MVVM 架构

WPF MVVM 架构 Step By Step(简单的三层架构示例及粘合代码GLUE code)

WPF MVVM 架构 Step By Step(把actions从view model解耦)

[译]WPF MVVM 架构 Step By Step(添加actions和INotifyPropertyChanged接口)

关于在MVVM架构下WPF中UserControl的 visibility Binding问题。 UserControl MVVM