C# WPF学习总结

目录

特点

MVVM

特点

是什么

理解一

理解二

优势

ViewModel和View的通信

双向绑定的情景

XAML

XAML是什么

XAML应用场景

绑定

Binding

MultiBinding

应用场景

MultiBinding+StringFormat

 MultiBinding+IMultiValueConverter

UpdateSourceTrigger

绑定模式

RelativeSource

Static Resources/Dynamic Resources

触发器

应用场景

Trigger

MultiTrigger

EventTrigger

 ControlTemplate中使用Trigger

DataTrigger

MultiDataTrigger

区别

控件

Page/UserControl/Window

DataTemplate/ControlTemplate/ItemsPanelTemplate

常用控件

常用的九种布局

Gird

StackPanel

WrapPanel

DockPanel

UniformGrid

Canvas

理解

示意图

ScrollViewer

ViewBox

​编辑

Border

Dispatcher

是什么

总结

依赖属性

是什么

为什么要有依赖属性

如何添加依赖属性

依赖属性的优势

依赖属性继承

只读依赖属性

附加属性

依赖属性验证

依赖属性的监听

依赖对象

事件

路由事件

冒泡路由事件

自定义路由事件

共享路由事件

引发和处理路由事件

附加事件

生命周期

DevExpress的应用

X:Name

WPF中ViewModel层弹出新窗口

WPF和WinForm区别

生态方面的区别

技术方面的区别

如何在WPF应用程序中全局捕获异常

特点

  1. WPF的特点是数据驱动UI,界面上所有的变化都是通过数据模型来推动的。
  2. 以数据为核心,WPF提供数据绑定的机制,当数据发生变化时,WPF自动发出通知并更新UI。

MVVM

特点

MVVM的特点就是降低了xaml文件和cs文件的耦合度。

是什么

C# WPF学习总结_第1张图片

理解一

  1. View就是用xaml实现的界面,负责与用户交互,接受用户输入,把数据展现给用户。
  2. ViewModel就是C#类,负责组装需要绑定的数据和命令,聚合Model对象,通过View类的DataContext 属性绑定到View上面。
  3. Model就是系统中的对象。
  4. View对应一个ViewModel,ViewModel可以聚合多个Model,ViewModel可以对应多View。

理解二

  1. Model就是现实世界中的对象。
  2. View就是UI。
  3. ViewModel就是对View的抽象。

优势

MVVM的优势就是把UI层和业务层进行分离,View就是负责如何显示数据和发送命令,ViewModel就是如何提供数据和执行命令。

ViewModel和View的通信

  1. 传递数据通过数据属性,需要实现INotifyPropertyChanged接口。
  2. 传递操作通过命令属性,需要实现ICommand接口。
  3. C# WPF学习总结_第2张图片

双向绑定的情景

  1. ObservableCollection中的对象发生改变,需要提供通知机制。
  2. 对象属性发生改变,需要提供通知机制。
  3. 集合的地址指向发生改变,也需要提供通知机制。

XAML

XAML是什么

XAML语言是一种声明性语言,每见到一个标签就声明一个实例。

  1. 定义:构建应用程序用户界面而创建的一种新的”可扩展应用程序标记语言”,提供一种便于扩展和定 位的语法来定义和程序业务逻辑分离的用户界面。
  2. 特点:
    1. 定义应用程序的界面元素
    2. 显式声明WPF资源(样式,模板,动画等)
    3. 集中关注界面设计
  3. 命名空间:xaml与.net程序语言一样,通过命名空间有效组织xaml内部的相关元素类。
  4. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 默认命名空间
  5. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xaml语法和编译相关的clr命名空间。
  6. 一个xmal文件至少要有两个命名空间。1.带x前缀。2.默认命名空间。
  7. 区分:应用时,不带前缀,来自于默认命名空间。否则来自于带前缀的命名空间。

XAML应用场景

  1. App.xaml:设置应用程序起始文件,系统及资源
  2. App.xaml.cs: App.xaml文件的后台类文件。
  3. StartupUri 指定起始文件
  4. 定义整个WPF应用程序的相关资源
  5. MainWindow.xaml:WPF应用程序界面与xaml设计文件。
  6. MainWindow.xmal.cs:xaml窗口文件的后台代码文件。

绑定

Binding

Binding是用来给UI界面绑定ViewMode的数据。

MultiBinding

应用场景

  1. MultiBinding可以进行联合绑定。
  2. 当在WPF中进行数据绑定时,比如TextBlock的Text属性,希望绑定两个或者两个以上的数据源,最 后得到的Text是由这几个数据源按照自己的设计组合而成,就要用到MultiBinding。

MultiBinding+StringFormat

C# WPF学习总结_第3张图片

 MultiBinding+IMultiValueConverter

 C# WPF学习总结_第4张图片

UpdateSourceTrigger

  1. Explicit表示手动更新,需要明确指定更新时机,来更新数据源。
  2. LostFocus表示失去焦点时更新数据源。
  3. PropertyChanged表示属性值发生改变时就更新数据源。

绑定模式

  1. OneWay是指源变更新目标。
  2. C# WPF学习总结_第5张图片
  3. TwoWay是指源变更新目标并且目标变更新源。
  4. OneTime是指只根据源设置目标,以后都不变。
  5. OneWayToSoure是指目标变更新源。
  6. Default是靠被指定的源或者目标是否有get属性或者set属性来进行指定。

RelativeSource

  1. RelativeSource常用的有五种查找模式。
  2. Self表示查找自身。
  3. FindAncestor表示查找父级,AncestorLevel表示父级级别,AncestorType表示父级类型。
  4. TemplateParent表示查找控件模板。
  5. Source表示指定数据源。
  6. Path表示指定属性。
  7. C# WPF学习总结_第6张图片

Static Resources/Dynamic Resources

  1. Static Resources是静态资源,编译时就确定。
  2. Dynamic Resources是动态资源,在运行时确定。可以动态修改,比如主题切换,多语言支持。

触发器

应用场景

触发器的主要作用就是根据Trigger的不同条件来自动更改外观的属性,或者执行一些动画操作。

Trigger

当鼠标滑过时字体变成红色。

C# WPF学习总结_第7张图片

MultiTrigger

当checkbox勾选并且鼠标滑过时字体变绿色。

C# WPF学习总结_第8张图片

EventTrigger

鼠标划入长度变长,鼠标移除长度变短。

C# WPF学习总结_第9张图片

 ControlTemplate中使用Trigger

C# WPF学习总结_第10张图片

DataTrigger

  1. 在ListBox中,当选中的Item为陕西省时,将Item项的文字颜色设置为红色。
  2. 当选中的Item为陕西省西安市时,将Item项的背景色设置为绿色。
  3. C# WPF学习总结_第11张图片

MultiDataTrigger

  1. HierarchicalDataTemplate:分层数据模板。
  2. 在TreeView中,当TreeViewItem没有展开并且TreeViewItem是一个目录时,显示目录图片。否则当 该TreeViewItem展开时,显示目录打开的图片。
  3. C# WPF学习总结_第12张图片
  4. 当所有的RadioButton都没有选中时,按钮不可用,否则按钮可用。
  5. C# WPF学习总结_第13张图片

区别

  1. Trigger和MultiTrigger都是触发器,只不过MultiTrigger是满足多个条件时才触发。
  2. DataTrigger和MultiDataTrigger也是触发器,MultiDataTrigger也是满足多个条件时才触发。
  3. Trigger和MultiTigger仅适用于同一控件中的属性,可以简单理解为面向控件的Property。
  4. DataTrigger和MultiDataTrigger的条件是基于绑定数据的属性值而不是UIElement的属性值,可以简单 理解为面向数据的Binding。
  5. MultiTrigger和MultiDataTrigger的条件都是在Conditions中编写的。

控件

Page/UserControl/Window

  1. Page通常用于承载网页。
  2. UserControl是用户控件,如果控件需要被重复使用时就可以使用用户控件,比如在很多窗口中,用同 一个自定义的日期控件。
  3. Window是主窗口,通常一个windows程序中只有一个主窗口。

DataTemplate/ControlTemplate/ItemsPanelTemplate

  1. DataTemplate是指数据模板。
  2. ControlTemplate是指控件模板。
  3. ItemsPanelTemplate是指项布局模板。

常用控件

  1. ShowInTaskbar 窗口是否具有任务栏按钮
  2. 内容控件:只能有一个子元素作为它的内容。
  3. WPF允许控件没有Name属性值,当后台代码需要引用对象的时候需要设置Name。
  4. RadioButton:同一组单选按钮,它们是互斥的关系。
  5. Border:边框,围绕在其它元素周围。
    1. 和布局面板一起使用,作为布局面板的边框。
    2. 作为任意控件的边框显示。
    3. Border只能有一个元素作为它的子元素。Border作为布局面板边框,布局面板内显示多个子元素。
  6. TextBlock和Lable区别:加载Labe比TextBlock耗费更多时间,label其实就是一个个性化的TextBlock, TextBlock比较底层只能显示文本。
  7. StackPanel:堆栈面板,子元素超出的部分会被隐藏。
  8. WrapPanel:流面板,子元素超出的部分会自动换行。
  9. DockPanel:停靠面板。特点:先添加的子元素,优先占用边角(优先占有权),所有子元素区域不会重叠。
  10. Canvas:画布面板(坐标面板),定义区域子元素的显示位置,指定相对于面板的坐标来定 位子元素显示 的位置。
    1. 附加属性:Canvas.Left Canvas.Right Canvas.Top Canvas.Bottom
    2. 坐标:(left,top) (left bottom) (right,top) (right,bottom)
    3. 不能子元素指定两个以上的附加属性,如果制定了,忽略后者。
    4. 当窗口大小变化,Canvas的尺寸就随之变动,子元素的位置也变化,但是子元素的坐标相对于 Canvas的位置没有变化。
    5. ClipToBounds 默认值false,溢出不裁剪。True,溢出裁剪。
    6. 应用:精确定位,画图,最简单的布局。
  11. Grid:网格面板,类似于WinForm中TableLayoutPanel,行和列方式布局页面或页面中某一块区域。每 个单元格可以包含一个元素或多个元素。
    1. Expander:折叠控件。
    2. Fram:支持导航,可以将一个页面导航到另一个页面,可能承载Page页。
    3. Page页:封装一页的内容。
    4. ListView:数据列表控件。用于显示数据项的列表。以列(GridViewColumn)形式显示数据项的视图模式。
  12. DataGrid:网格控件,可以自定义网格显示数据的控件。
    1.  DataGrid属性:

      1. RowHeaderTemplate:行标题模板

      2. CanUserAddRows:是否添加新行

      3.  IsReadOnly:是否可以编辑其中的值

      4. VerticalScrollBarVisibility/HorizontalScrollBarVisibility 垂直/水平滚动条的显示

      5. CurrentItem:当前单元格的行绑定的数据项

      6.  CanUserDeleteRows:是否可以删除行

      7.  RowStyle/CellStyle:行/单元格 样式

      8. HeaderVisibility:行和列头的可见性

      9. AlternatingRowsBAckground:交替行上使用的背景画笔

      10. GridLinesVisibility:显示哪些网格线

      11. VerticalGridLinesBrush/HorizontalGridLinesBrush 垂直/水平网格线画笔

      12. RowHeaderWidth行标题宽度,ColumnHeaderHeight列标题高度,RowHeight行高

      13. AutoGenerateColumns:是否自动创建列

      14. SelectionUnit/SelectionMode:选择单元(单元格,行或者两者) /单选或多选

    2.  DataGrid中的列:

      1. DataGridTextColum:文本显示内容,数据类型为String

      2.  DataGridCheckBoxColumn:复选框的形式显示内容,数据类型为Boolean

      3. DataGridComboBoxColumn:下拉列表的形式显示内容,数据类型为Enum

      4. DataGridHyperlinkColumn:超链接的形式显示内容,数据类型为Uri

      5.  DataGridTemplateColumn:模板列,自定义显示样式

  13. UniformGrid:界面均等份布局。

  14. Menu:Windows菜单控件。
    1. Menu属性:
      1. IsMainMenu:是否接受主菜单激活通知,alt或F10激活。
      2. MenuItem:Menu控件中的可选项,带标题的条目控件。
      3. ContextMenu:特定于某个元素之上的功能菜单。右键菜单,上下文菜单。
    2. ContextMenu属性:HorizontalOffset,VertiCalOffset 右键菜单控件相对于点击位置的水平,垂直距离点。
    3. TreeView:树形控件,以节点的形式显示数据。节点对应树形控件的项,项可以展开与折叠。
      1. SelectedItem:选择的项
      2. SelectedValue:选择项的值
      3. ItemSource:数据源
      4. ToolBar:工具栏控件。为一组命令或控件提供的容器。
  15. ToolBar属性
    1. Orientation:指示内部项的布局方向,只读属性。
    2. ToolBarTray:布局ToolBar的容器,呈放多个ToolBar。
  16. StatusBar:状态栏控件。
  17. MediaElement:媒体播放控件,音频或视频文件。
  18. RichTextBox:对流文档(FlowDocument)对象进行操作的丰富编辑控件。
  19. C# WPF学习总结_第14张图片
  20. C# WPF学习总结_第15张图片

常用的九种布局

Gird

  1. Grid是网格面板,最常用的布局容器,就是整体的页面布局。
  2. 注意:
    1. 固定长度:值为一个确定的数字。
    2. 自动长度:值为Auto,就是取实际控件所需要的最小值。
    3. 比例长度:*表示占用剩余的全部长度。一个长度为2*,一个长度为*,2*表示占剩余全部长度的2/3,*表示占剩余全部长度的1/3。

StackPanel

StackPanel是堆栈面板,按照行或者列进行顺序排列,不会换行。

WrapPanel

WrapPanel是流面板,在有限的容器范围内,可以自动换行或者换列。

DockPanel

DockPanel是停靠面板,让元素停靠在整个面板的某一条边上,然后拉伸元素填满全部的宽度或者高度。

UniformGrid

UniformGrid是Grid的简化版,可以进行界面均等份布局,每个单元格大小相同。

Canvas

理解

Canvas类似于坐标系的面板,所有的元素通过设置坐标来决定其在坐标系中的位置。

示意图

C# WPF学习总结_第16张图片

C# WPF学习总结_第17张图片 

ScrollViewer

ScrollViewer是带有滚动条的面板,在ScrollViewer中只能有一个子控件,如果要显示多个子控件,需要通过Panel控件进行包裹。

ViewBox

  1. ViewBox的作用是拉伸或者延展位于其中的组件,用来填满可用的控件。ViewBox中只能有一个子控件, 如果要显示多个子控件,需要通过Panel控件进行包裹。
  2. 常用属性:
    1. Stretch:获取或者设置拉伸模式,用来决定该组件中的内容应该用怎样的形式填充该组件的已有空间,默认值为Uniform。
    2. C# WPF学习总结_第18张图片

Border

Border是一个装饰控件,用来绘制边框和背景。Border中只能有一个子控件,如果要显示多个子控件,需要通过Panel控件进行包裹。

Dispatcher

是什么

Dispatcher属性可以将其它线程投放到UI线程,让UI线程去执行。

总结

  1. 在WPF中,所有的对象都派生自DispatcherObject对象,DispatcherObject对象通过Dispatcher属性用 来获取创建对象线程对应的Dispatcher属性。
  2. DispatcherObject对象只能被创建它的线程所访问,其它线程修改DispatcherObject对象时需要取得对 应的Dispatcher属性,调用Invoke方法或者BeginInvoke方法来投入任务。
  3. Invoke方法和BeginInvoke方法从WinForm时代就是一直存在的,只是在WPF中使用了Dispatcher属 性来封装这些线程级的操作。

依赖属性

是什么

  1. 依赖属性是自己没有值,需要通过绑定从其它数据源获取值的属性。
  2. 只有依赖属性才能进行绑定。

为什么要有依赖属性

  1. 在传统的OOP中,多级继承的时候,父类的字段都被继承,子类占用内存空间不可避免的膨胀。
  2. 而且在多级继承中,大多数字段并没有被修改,为了减少对象的体积,从而需要依赖属性。
  3. 在WinForm中,每个UI控件的属性都被赋予了初始值,每个相同的控件在内存中都会保存一份初始值。
  4. WPF的依赖属性在内部使用哈希表的存储机制,对多个相同控件的相同属性值只保存一份。

如何添加依赖属性

C# WPF学习总结_第19张图片

依赖属性的优势

  1. 依赖属性主要解决了传统OOP多级继承中,大多数字段值不改变的情况,减少了内存占比。
  2. 依赖属性是通过调用DependencyObject对象的GetValue方法和SetValue方法来对依赖属性进行读写 的。
  3. DependencyObject对象使用了哈希表的存储机制,对应的Key就是属性的HashCode值,而值就是注 册的DependencyProperty属性。
  4. 依赖属性是以数据为中心,当数据源发生改变时,关联的UI数据也会改变。
  5. 依赖属性的值可以通过Binding依赖于其它对象上,这就使得数据源一变动,依赖于此数据源的依赖属 性全部进行更新。

依赖属性继承

通过AddOwer方法可以继承其它控件的依赖属性。

C# WPF学习总结_第20张图片

只读依赖属性

只读依赖属性是用

DependencyProperty.RegisterReadonly方法来替换DependencyProperty.Register方法。

C# WPF学习总结_第21张图片

附加属性

附加属性最常见的场景就是布局容器中DockPanel和Grid的附加属性。

C# WPF学习总结_第22张图片

 C# WPF学习总结_第23张图片

 附加属性是用RegisterAttached方法替代了Register方法。

C# WPF学习总结_第24张图片

依赖属性验证

  1. ValidateValueCallback函数可以接受或拒绝新值,验证值是否合法。
  2. CoerceValueCallback函数可以将新值强制修改为可被接受的值。
  3. PropertyChangedCallback函数可以触发依赖属性值的更改,当值发生改变时,可以做一些操作。
  4. C# WPF学习总结_第25张图片

依赖属性的监听

  1. 第一种方法是使用PropertyChangedCallback函数进行监听。
  2. C# WPF学习总结_第26张图片
  3. 第二种方法是获取DependencyPropertyDescriptor对象,并调用AddValueChange方法为其绑定一个回 调函数进行监听。
  4. C# WPF学习总结_第27张图片

依赖对象

  1. 对象创建时不包含字段所占用的空间,在使用这个字段时通过其它对象的数据来分配空间,这种对象 就是依赖对象。
  2. 这种分配空间的能力就是依靠依赖属性来实现的。

事件

路由事件

  1. 直接路由事件,它源自一个元素,并且不传递给其它的元素,比如MouseEnter事件就是当鼠标移动到 一个元素上面时触发的事件,它就是一个直接路由事件。
  2. 冒泡事件是指从事件源传递到根元素,也就是在包含层次中向上传递的事件,比如MouseDown事件 就是一个冒泡路由事件。它首先被单击的元素触发,然后就是该元素的父元素触发,以此类推,直到 到达WPF元素树的顶部为止。
  3. 隧道(Preview)事件是指从根元素传递到事件源,也就是在包含层次中向下传递的事件,比如 PreviewKeyDown就是一个隧道路由事件。在一个窗口上按下某个键,首先是窗口,然后是更具体的容 器,直到到达按下键时具有焦点的元素。
  4. 隧道路由事件总是在冒泡路由事件之前被触发。
  5. 如果将隧道路由事件标记为已处理的,那么冒泡路由事件就不会发生,这是因为这两个事件共享同一 个RoutedEventArgs类的实例。
  6. 隧道路由事件可以用来执行一些预处理操作,比如根据键盘上特定的键执行特定的操作,或过滤掉特 定的鼠标操作,都可以在隧道路由事件处理程序中进行处理。

冒泡路由事件

  1. 在设置Handled=true的时候,不管是冒泡事件还是隧道事件,它还是会继续传播的,只是对应的事件 不会在被处理了。
  2. 如果想继续响应相应的事件,可以通过AddHandler方法进行注册。
  3. 每当触发事件处理程序之前,都会检查RoutedEventArgs的Handled属性和_handleEventsToo 字段。当 Handle=true时,其实路由事件还是一样会传递,传递到对应事件的处理程序中时,只是因为 Handle为true和_handleEventsToo为false,从而导致事件处理程序没有运行。
  4. 如果通过AddHandler(RoutedEvent,Delegate,Boolean)注册事件处理程序。
  5. 把_handleEventToo显示设置 为true,所以即使Handle为true,该元素的事件处理程序照样会被执行,因为此时的if条件一样会为 true。
  6. C# WPF学习总结_第28张图片
  7. C# WPF学习总结_第29张图片

自定义路由事件

路由事件由只读的静态字段表示,在一个静态构造函数通过

EventManager.RegisterRoutedEvent函数注册,然后定义一个事件进行包装。

C# WPF学习总结_第30张图片

共享路由事件

  1. 可以在类之间共享路由事件的定义,实现路由事件的继承。
  2. 比如UIElement类和ContentElement类都使用了MouseUp事件,但是MouseUp事件是由Mouse类定 义的。
  3. 所以UIElement类和ContentElement类只是通过RouteEvent.AddOwner方法重用了MouseUp事件。
  4. C# WPF学习总结_第31张图片

引发和处理路由事件

路由事件通过RaiseEvent方法触发,所有的元素都从UIElement类继承了该方法。

C# WPF学习总结_第32张图片

附加事件

  1. 比如StackPanel面板中包含了一堆按钮,现在希望在一个事件处理程序中处理所有这些按钮的单击事 件。
  2. 可以将每个按钮的Click事件关联到同一个事件处理程序中,但是Click事件支持事件冒泡,所以可以 通过更高层次的元素来关联Click事件处理所有按钮的单击事件。
  3. C# WPF学习总结_第33张图片

生命周期

  1. SourceInitialized事件在取得窗口句柄属性时触发。
  2. Activated事件在窗口获取焦点时触发。
  3. Loaded事件在窗口加载时触发。
  4. ContentRendered事件在窗口第一次呈现结束后立即触发。
  5. Activated事件在窗口获取焦点时触发。
  6. Deactivate事件在窗口失去焦点时触发。
  7. Closing事件在窗口关闭过程中触发。
  8. UnLoaded事件在窗口卸载时触发。
  9. Closed事件在窗口关闭完成后触发。

DevExpress的应用

  1. POCOViewModel特性:不用在View层中指定DataContext,就可以指定对应的ViewModel。
  2. 属性标记为Virtual进行数据双向绑定。
  3. 方法在View层绑定的时候用Command结尾,而ViewModel层不需要Command结尾来进行命令绑定。
  4. 依赖注入通过ServiceContainer.Default.RegisterService()进行注入。
  5. 依赖注入获取通过ServiceContainer.Default.GetRequiredService获取。
  6. View层常用转换:
    1. BooleanNegationConverter
    2. BooleanToObjectConverter
    3. BooleanToVisibility
    4. ObjectToBooleanConvert
    5. StringToBooleanConvert
    6. StringToVisibiltyConverter
  7. 布局:
  8. C# WPF学习总结_第34张图片

X:Name

X:Name:实例类型不是派生在FrameworkElement上时,用x:Name来设置别名。

WPF中ViewModel层弹出新窗口

  1. ViewModel定义EventHandler事件,View层用EventHandler事件打开委托,ViewModel中通过按钮的 Command触发EventHandler。
  2. Dictonary注册窗体的Type和key,反射创建窗体对象打开窗体。
  3. Dictonary注册窗体的Type和委托(Action,Func),执行委托打开窗体,委托包装的方法,在窗体内部执 行打开窗体的逻辑。

WPF和WinForm区别

生态方面的区别

  1. 现在西安很多公司,尤其是传统行业大部分用的还是WinForm。
  2. 因为很多公司的用户对界面的美观性要求不高,你只要给我把功能实现了就可以了,所以用WinFrom 就非常合适。WinFrom就是拖拉拽,能非常快速的开发出一个功能不复杂的程序,并且用起来还比较 流畅。对于大多数公司来说成本低,不需要那么多研发,而且公司也养不了那么研发,一般最多2到 3个人用WinFrom开发程序,然后维护,甚至有时候就是一个人。
  3. 如果用户对界面的美观性要求非常高,并且任何按钮,组件都需要按照要求定制化开发,里面还包含 了各种动画效果以及各种3D显示效果,这个时候就必须考虑使用WPF。如果用了WPF但是又没有那 么多人去做,基本上做的人就相当于全栈开发。
  4. 首先WPF的学习成本比WinFrom高的多,WPF不是拖拉拽就能完成开发,定制化高的软件都需要程 序员去写xmal来实现,xmal包含了各种样式和各种触发器,以及各种各样五花八门非常灵活的数据 绑定。
  5. 而且用WPF就得考虑视图和数据分离,前后端分离,这就相当于程序员既要写xaml还要写业务,甚 至还要写接口,工作量会非常大。当然WPF也可以像WinFrom那样不使用MVVM,不进行视图和数 据的分离,所有的事件和业务都写到xaml对应的cs文件中,然后写个DBHelper啥的直接访问数据库, 这样做如果公司研发团队就几个开发为了提高效率没啥问题。如果团队比较大,人比较多,像某些公 司研发加起来50多个人,就得分工明确,让专门写xaml的去写xaml,专门写业务的去写ViewModel, 专门写接口的去写gRPC接口,这么做最大的好处就是可以降低系统的耦合度,后面维护起来也方便, 专人专职去做自己擅长的事情。

技术方面的区别

  1. WinForm本身的开发模式,存在天然的缺陷。给一个WinForm控件进行数据绑定操作,然后按照事件 驱动的模式,根据控件名来获取原始绑定的数据,界面和数据是完全耦合。
  2. WPF是MVVM模式,数据和视图分离,不再为每个元素添加固定的名称,通过数据驱动进行业务 代码编写。
  3. WinForm的设计器和cs文件的代码耦合度是非常高的,不能独立进行页面设计。
  4. WPF是数据驱动UI,数据是核心,处于主动地位。UI从属于数据,并且表达数据,处于被动地位。
  5. WinForm中,每个UI控件的属性都被赋予了初始值,每个相同的控件在内存中都会保存一份初始值。
  6. WPF依靠依赖属性解决了在传统OOP多级继承中,大多数字段值不改变的情况,减少了内存占比。
  7. WPF底层使用Direct X接口,加强了3D图形和声音效果。
  8. WinForm底层使用GDI+接口,主要是负责绘图程序之间的信息交换和处理,以及所有windows程序的 图形输出。

如何在WPF应用程序中全局捕获异常

Application.DispatcherUnhandledException

你可能感兴趣的:(wpf,c#,.net)