WPF 与 C# 融合开发:从基础到高级应用(一)
WPF 与 C# 融合开发:从基础到高级应用
一、C# 语言基础回顾
1.1 C# 语言概述
C# 是微软开发的一种现代、面向对象的编程语言,它融合了 C、C++ 和 Java 等语言的优点,具有简洁、安全、高效等特点。C# 广泛应用于 Windows 平台的应用开发,是开发 WPF 应用程序的首选语言。
1.2 数据类型与变量
1.2.1 值类型
值类型直接存储数据的值,在栈上分配内存。常见的值类型包括整数类型(如 sbyte
、ushort
、uint
、ulong
等)、浮点类型(decimal
常用于财务计算,具有高精度)、布尔类型和字符类型。例如:
decimal price = 123.45m;
bool isMember = false;
1.2.2 引用类型
引用类型存储的是数据的引用,在堆上分配内存。类、接口、数组、委托和字符串都是引用类型。例如:
string message = "Hello, C#!";
int[] numbers = new int[5];
1.2.3 变量声明与作用域
变量在使用前必须声明,并且具有一定的作用域。作用域决定了变量的可见性和生命周期。例如:
{
int localVariable = 10; // 局部变量,作用域在大括号内
}
// 这里无法访问 localVariable
1.3 控制结构
1.3.1 条件语句
除了常见的 if - else
和 switch
语句,C# 还支持三元运算符 ?:
,用于简洁地表达简单的条件判断。例如:
int age = 20;
string status = age >= 18 ? "成年人" : "未成年人";
1.3.2 循环语句
C# 提供了 for
、while
、do - while
和 foreach
循环。foreach
循环常用于遍历数组或集合。例如:
string[] names = { "Alice", "Bob", "Charlie" };
foreach (string name in names)
{
Console.WriteLine(name);
}
1.4 方法和类
1.4.1 方法定义和调用
方法是具有特定功能的代码块,可以接受参数并返回值。方法可以重载,即方法名相同但参数列表不同。例如:
class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
public double Add(double a, double b)
{
return a + b;
}
}
1.4.2 类的封装和继承
类是对象的蓝图,封装了数据和行为。继承允许一个类继承另一个类的属性和方法,提高代码的复用性。例如:
class Animal
{
public void Eat()
{
Console.WriteLine("动物吃东西");
}
}
class Cat : Animal
{
public void Meow()
{
Console.WriteLine("猫叫");
}
}
1.5 异常处理
C# 提供了 try - catch - finally
语句来处理异常。try
块中放置可能会抛出异常的代码,catch
块用于捕获和处理异常,finally
块无论是否发生异常都会执行。例如:
try
{
int result = 10 / 0;
}
catch (DivideByZeroException ex)
{
Console.WriteLine("除数不能为零:" + ex.Message);
}
finally
{
Console.WriteLine("无论是否异常,此代码都会执行");
}
二、WPF 基础架构
2.1 WPF 概述
WPF 是微软为 Windows 平台开发的新一代用户界面框架,它引入了 DirectX 图形渲染引擎,支持硬件加速,能够创建出高质量的 2D 和 3D 图形界面。WPF 使用 XAML 来描述用户界面,实现了界面设计和代码逻辑的分离。
2.2 XAML 基础
2.2.1 XAML 语法规则
XAML 是一种基于 XML 的标记语言,遵循 XML 的语法规则。标签用于表示控件和元素,属性用于设置控件的特性。例如:
<Button Content="点击我" Width="100" Height="30"/>
2.2.2 命名空间的使用
在 XAML 中,命名空间用于引用不同的程序集和类型。常见的命名空间包括 http://schemas.microsoft.com/winfx/2006/xaml/presentation
和 http://schemas.microsoft.com/winfx/2006/xaml
。例如:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="My Window" Height="350" Width="525">
<!-- 窗口内容 -->
</Window>
2.3 布局控件
2.3.1 Grid 布局
Grid
布局将界面划分为行和列的网格,控件可以放置在指定的单元格中。可以通过 RowDefinitions
和 ColumnDefinitions
来定义行和列的大小。例如:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="用户名:" Grid.Row="0" Grid.Column="0"/>
<TextBox Grid.Row="0" Grid.Column="1"/>
</Grid>
2.3.2 StackPanel 布局
StackPanel
布局按顺序排列子控件,可以是水平排列或垂直排列。通过 Orientation
属性来指定排列方向。例如:
<StackPanel Orientation="Horizontal">
<Button Content="按钮1"/>
<Button Content="按钮2"/>
</StackPanel>
2.3.3 WrapPanel 布局
WrapPanel
布局当子控件超出其宽度或高度时,会自动换行或换列排列。例如:
<WrapPanel>
<Button Content="按钮1"/>
<Button Content="按钮2"/>
<Button Content="按钮3"/>
</WrapPanel>
2.4 控件基础
2.4.1 常见控件介绍
WPF 提供了丰富的控件,如 Button
、TextBox
、Label
、ListBox
、ComboBox
等。每个控件都有其特定的用途和属性。例如:
<StackPanel>
<Label Content="请输入文本:"/>
<TextBox Name="inputTextBox"/>
<Button Content="提交" Click="Button_Click"/>
</StackPanel>
2.4.2 控件事件处理
控件的事件可以在 XAML 中指定事件处理方法,也可以在代码中动态注册。例如,处理按钮的 Click
事件:
private void Button_Click(object sender, RoutedEventArgs e)
{
string input = inputTextBox.Text;
MessageBox.Show("你输入的文本是:" + input);
}
三、WPF 数据绑定深入探究
3.1 数据绑定基础
3.1.1 数据绑定概念
数据绑定是 WPF 的核心特性之一,它允许将 UI 元素的属性与数据源的属性进行关联,实现数据的自动更新。
3.1.2 简单数据绑定示例
假设有一个 Person
类:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
在 XAML 中进行数据绑定:
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Age}"/>
</StackPanel>
在代码隐藏文件中设置数据上下文:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Person person = new Person { Name = "David", Age = 28 };
DataContext = person;
}
}
3.2 数据绑定模式
3.2.1 单向绑定
单向绑定是指数据源的属性值发生变化时,UI 元素会更新,但 UI 元素的变化不会影响数据源。使用 Mode=OneWay
来指定单向绑定。例如:
<TextBlock Text="{Binding Name, Mode=OneWay}"/>
3.2.2 双向绑定
双向绑定允许数据源和 UI 元素之间的相互更新。使用 Mode=TwoWay
来指定双向绑定。例如:
<TextBox Text="{Binding Name, Mode=TwoWay}"/>
3.2.3 单向到源绑定
单向到源绑定是指 UI 元素的变化会更新数据源,但数据源的变化不会影响 UI 元素。使用 Mode=OneWayToSource
来指定单向到源绑定。
3.3 数据模板
3.3.1 数据模板概念
数据模板用于定义如何显示数据源中的数据。可以使用数据模板来定制列表框、组合框等控件中数据的显示方式。
3.3.2 数据模板示例
假设有一个 Employee
类:
public class Employee
{
public string Name { get; set; }
public int EmployeeId { get; set; }
}
在 XAML 中定义数据模板:
<Window.Resources>
<DataTemplate x:Key="EmployeeTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="5"/>
<TextBlock Text="{Binding EmployeeId}" Margin="5"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding Employees}" ItemTemplate="{StaticResource EmployeeTemplate}"/>
在代码隐藏文件中设置数据源:
public partial class MainWindow : Window
{
public ObservableCollection<Employee> Employees { get; set; }
public MainWindow()
{
InitializeComponent();
Employees = new ObservableCollection<Employee>
{
new Employee { Name = "Eve", EmployeeId = 3 },
new Employee { Name = "Frank", EmployeeId = 4 }
};
DataContext = this;
}
}
3.4 数据验证
3.4.1 数据验证概念
数据验证用于确保用户输入的数据符合特定的规则。WPF 提供了多种方式来实现数据验证,如自定义验证规则、使用 IDataErrorInfo
接口等。
3.4.2 自定义验证规则示例
定义一个自定义验证规则类:
public class AgeValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
int age;
if (!int.TryParse(value.ToString(), out age))
{
return new ValidationResult(false, "年龄必须是数字");
}
if (age < 0 || age > 120)
{
return new ValidationResult(false, "年龄必须在 0 到 120 之间");
}
return ValidationResult.ValidResult;
}
}
在 XAML 中使用自定义验证规则:
<TextBox>
<TextBox.Text>
<Binding Path="Age" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:AgeValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
四、WPF 样式与模板高级应用
4.1 样式基础
4.1.1 样式概念
样式是一组属性值的集合,用于定义控件的外观和行为。可以使用样式来统一应用程序中相同类型控件的外观。
4.1.2 样式定义与使用
在 XAML 中定义样式:
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="LightBlue"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="16"/>
</Style>
</Window.Resources>
<Button Content="Styled Button"/>
4.2 模板基础
4.2.1 模板概念
模板用于定义控件的可视化结构。可以使用模板来完全自定义控件的外观。
4.2.2 模板定义与使用
例如,自定义按钮的模板:
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Button Content="Custom Button"/>
4.3 资源管理
4.3.1 资源概念
资源是可以在应用程序中重复使用的对象,如样式、模板、图像等。可以将资源定义在 XAML 的 Resources
部分,然后在需要的地方引用。
4.3.2 资源的使用
例如,定义一个颜色资源并在样式中使用:
<Window.Resources>
<SolidColorBrush x:Key="MyButtonBackground" Color="Green"/>
<Style TargetType="Button">
<Setter Property="Background" Value="{StaticResource MyButtonBackground}"/>
</Style>
</Window.Resources>
<Button Content="Button with Resource"/>
4.4 主题和皮肤切换
4.4.1 主题和皮肤概念
主题和皮肤用于改变应用程序的整体外观。可以通过切换不同的资源字典来实现主题和皮肤的切换。
4.4.2 主题切换示例
创建不同的资源字典文件,如 LightTheme.xaml
和 DarkTheme.xaml
,在代码中动态加载不同的资源字典:
private void SwitchToLightTheme()
{
ResourceDictionary lightTheme = new ResourceDictionary();
lightTheme.Source = new Uri("LightTheme.xaml", UriKind.Relative);
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(lightTheme);
}
private void SwitchToDarkTheme()
{
ResourceDictionary darkTheme = new ResourceDictionary();
darkTheme.Source = new Uri("DarkTheme.xaml", UriKind.Relative);
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(darkTheme);
}