编辑
2025-02-03
WinForm到WPF转型
00
请注意,本文编写于 92 天前,最后修改于 92 天前,其中某些信息可能已经过时。

目录

渲染机制
WinForm
WPF
布局系统
WinForm
WPF
数据绑定
WinForm
WPF
控件自定义
WinForm
WPF
事件处理
WinForm
WPF
开发模式
WinForm
WPF
总结

在Windows应用程序开发中,WinForm和WPF是两种主要的技术框架。它们各自有不同的设计理念、渲染机制和开发模式。本文将详细探讨WPF与WinForm的本质区别,并通过示例进行说明。

渲染机制

WinForm

WinForm基于Windows GDI/GDI+进行渲染,这是一种基于CPU的渲染技术。每个控件都是Windows原生控件的封装,适合简单的用户界面。

示例:在WinForm中绘制自定义图形

C#
protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); Graphics g = e.Graphics; g.DrawEllipse(Pens.Red, 10, 10, 100, 100); g.FillRectangle(Brushes.Blue, 120, 10, 100, 100); }

image.png

WPF

WPF使用DirectX进行渲染,是一种基于GPU的渲染技术。所有控件都是由矢量图形组成,能够充分利用GPU加速,处理复杂动画和图形效果。

示例:在WPF中绘制相同图形

XML
<Canvas> <Ellipse Width="100" Height="100" Margin="10,10,0,0" Stroke="Red" StrokeThickness="1"/> <Rectangle Width="100" Height="100" Margin="120,10,0,0" Fill="Blue"/> </Canvas>

image.png

布局系统

WinForm

WinForm使用基于像素的绝对定位系统,控件位置通过坐标确定。虽然可以使用Dock等方法进行布局,但相对较为复杂。

示例:WinForm布局

C#
button1.Location = new Point(10, 10); button1.Size = new Size(100, 30); button2.Location = new Point(120, 10); button2.Size = new Size(100, 30);

WPF

WPF采用基于容器的流式布局系统,提供多种布局面板(如StackPanel、Grid等),使得界面设计更加灵活。

示例:WPF布局

XML
<StackPanel> <Button Width="100" Height="30" Margin="5" Content="Button 1"/> <Button Width="100" Height="30" Margin="5" Content="Button 2"/> </StackPanel> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="2*"/> </Grid.ColumnDefinitions> <Button Grid.Column="0" Content="Left"/> <Button Grid.Column="1" Content="Right"/> </Grid>

image.png

数据绑定

WinForm

WinForm提供简单的数据绑定机制,主要用于Windows Forms控件和数据源之间的绑定。

示例:WinForm数据绑定

C#
public class Person { public string Name { get; set; } public int Age { get; set; } } // 在窗体中 Person person = new Person { Name = "John", Age = 30 }; textBox1.DataBindings.Add("Text", person, "Name"); numericUpDown1.DataBindings.Add("Value", person, "Age");

WPF

WPF提供了强大的数据绑定系统,支持多种绑定模式和转换器,能够实现更复杂的数据交互。

示例:WPF数据绑定

XML
<Window x:Class="AppWpf.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:AppWpf" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Window.Resources> <local:AgeConverter x:Key="AgeConverter"/> </Window.Resources> <Grid> <StackPanel Margin="20"> <TextBlock Text="个人信息" FontSize="18" Margin="0,0,0,10"/> <StackPanel Orientation="Horizontal" Margin="0,0,0,10"> <TextBlock Text="姓名:" Width="100"/> <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Width="200"/> </StackPanel> <StackPanel Orientation="Horizontal" Margin="0,0,0,10"> <TextBlock Text="年龄:" Width="100"/> <TextBox Text="{Binding Age, Converter={StaticResource AgeConverter}}" Width="200"/> </StackPanel> <StackPanel Orientation="Horizontal" Margin="0,0,0,10"> <TextBlock Text="显示信息:" Width="100"/> <TextBlock Text="{Binding DisplayInfo}" FontWeight="Bold"/> </StackPanel> </StackPanel> </Grid> </Window>
C#
public class PersonViewModel : INotifyPropertyChanged { private string _name; private int _age; public string Name { get => _name; set { _name = value; OnPropertyChanged(); UpdateDisplayInfo(); } } public int Age { get => _age; set { _age = value; OnPropertyChanged(); UpdateDisplayInfo(); } } private string _displayInfo; public string DisplayInfo { get => _displayInfo; private set { _displayInfo = value; OnPropertyChanged(); } } private void UpdateDisplayInfo() { DisplayInfo = string.IsNullOrEmpty(Name) ? "请输入姓名" : $"{Name}的年龄是{Age}岁"; } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string name = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } }

image.png

控件自定义

WinForm

WinForm主要通过属性设置和重写绘制方法来自定义控件外观。

示例:自定义WinForm按钮外观

C#
public class CustomButton : Button { protected override void OnPaint(PaintEventArgs pevent) { Graphics g = pevent.Graphics; Rectangle rect = ClientRectangle; g.FillRectangle(Brushes.Blue, rect); using (StringFormat sf = new StringFormat()) { sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; g.DrawString(Text, Font, Brushes.White, rect, sf); } } }

image.png

WPF

WPF允许通过样式和模板来定义控件的外观,提供了更强大的样式定制能力。

示例:WPF按钮样式

XML
<Style TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="border" Property="Background" Value="Red"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>

image.png

事件处理

WinForm

WinForm使用传统的事件处理机制,事件处理相对简单。

示例:WinForm事件处理

C#
public partial class Form1 : Form { public Form1() { InitializeComponent(); button1.Click += Button1_Click; } private void Button1_Click(object sender, EventArgs e) { MessageBox.Show("Button Clicked!"); } }

WPF

WPF使用更复杂的路由事件系统,支持事件隧道和冒泡,提供更灵活的事件处理方式。

示例:WPF路由事件

XML
<StackPanel PreviewMouseDown="StackPanel_PreviewMouseDown"> <Button Content="Click Me" MouseDown="Button_MouseDown"/> </StackPanel>
C#
private void StackPanel_PreviewMouseDown(object sender, MouseButtonEventArgs e) { // 隧道事件 - 首先触发 Debug.WriteLine("StackPanel Preview"); } private void Button_MouseDown(object sender, MouseButtonEventArgs e) { // 冒泡事件 - 随后触发 Debug.WriteLine("Button MouseDown"); }

开发模式

WinForm

WinForm适合快速原型开发,具有平缓的学习曲线,特别适合初学者和简单应用的开发。

WPF

WPF采用MVVM(Model-View-ViewModel)模式,适合大型应用程序开发,支持组件化和模块化特性。

总结

WinForm和WPF各有其独特的优势和适用场景。WinForm以其简单易用和快速开发的特点,适合初学者和小型企业应用。而WPF则凭借其强大的图形处理能力、灵活的布局和数据绑定机制,适合构建复杂的企业级应用。对于开发者来说,理解这两者的本质区别,有助于选择合适的技术框架来满足项目需求。

本文作者:rick

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!