目录

C#(WPF)-八股文

目录

第一部分:WPF 核心知识


1. 什么是 WPF?和 WinForms 有什么区别?

WPF 是基于 DirectX 的桌面 UI 框架,使用 XAML 构建界面。

对比项 WPF WinForms
渲染引擎 DirectX GDI/GDI+
界面描述 XAML + C# 纯 C# / 设计器
数据绑定 强大 较弱
样式模板 支持 基本不支持
动画 支持 基本不支持
架构模式 适合 MVVM 事件驱动

2. WPF 的核心特点

  • XAML
  • 数据绑定
  • 依赖属性
  • 路由事件
  • 样式与模板
  • 动画
  • MVVM

3. 什么是 XAML?

  • XAML 是一种声明式标记语言,用来描述 UI。
  • 本质上会被编译成 BAML,再由 WPF 加载生成对象树。
  • 优点是 界面和业务逻辑分离

4. 什么是逻辑树(Logical Tree)和视觉树(Visual Tree)?

  • 逻辑树:描述控件之间的逻辑包含关系,比如 Window -> Grid -> Button。
  • 视觉树:描述控件最终渲染出来的完整结构,包含模板生成的内部元素。
  • 查找控件、事件路由、样式应用时常会涉及这两个概念。

5. 什么是依赖属性(DependencyProperty)?

WPF 特有属性系统,不只是普通 CLR 属性。

支持:

  • 数据绑定
  • 样式
  • 动画
  • 默认值
  • 属性值继承
  • 变更通知

常用于自定义控件。


6. 依赖属性和普通属性有什么区别?

  • 普通属性:只是字段封装。
  • 依赖属性:由 WPF 属性系统管理,可参与绑定、动画、样式等。
  • 一般控件公开可绑定的属性,优先考虑依赖属性。

7. 如何注册一个依赖属性?

public static readonly DependencyProperty TitleProperty =
    DependencyProperty.Register(
        "Title",
        typeof(string),
        typeof(MyControl),
        new PropertyMetadata("默认值"));

public string Title
{
    get => (string)GetValue(TitleProperty);
    set => SetValue(TitleProperty, value);
}

8. 什么是附加属性(Attached Property)?

  • 某个类定义的属性,可以"附加"到别的对象上使用。
  • 典型例子:Grid.RowCanvas.Left
  • 本质上也是依赖属性。

9. 什么是路由事件(RoutedEvent)?

事件可以在元素树中传播,不只是当前控件自己处理。

三种类型:

  • 冒泡(Bubbling):从源控件向父级传播,如 Click
  • 隧道(Tunneling):从根向源控件传播,一般以 Preview 开头,如 PreviewMouseDown
  • 直接(Direct):只在当前控件触发

10. 什么是数据绑定(Binding)?

  • 将 UI 和数据对象连接起来。
  • UI 显示数据、用户修改数据时可同步到对象。
  • 是 WPF 和 MVVM 的核心。

11. 常见 Binding Mode 有哪些?

模式 说明
OneWay 数据源 -> UI
TwoWay 双向同步
OneTime 只绑定一次
OneWayToSource UI -> 数据源
Default 使用控件默认模式

常见追问:

  • TextBox.Text 默认是 TwoWay
  • UpdateSourceTrigger 默认通常是 LostFocus

12. 什么是 DataContext?

  • DataContext 是绑定时默认的数据源。
  • 它会沿着视觉/逻辑树向下继承。
  • 子元素没显式指定 Source 时,会自动使用 DataContext。

13. Binding 中 Source、ElementName、RelativeSource 的区别?

属性 说明
Source 手动指定数据源对象
ElementName 绑定到某个控件
RelativeSource 绑定到相对位置对象,如自己、父元素、TemplatedParent

14. UpdateSourceTrigger 有哪些?

说明
PropertyChanged 属性变化立即更新
LostFocus 失去焦点更新
Explicit 手动更新

15. 什么是 INotifyPropertyChanged?

当对象属性变化时通知 UI 刷新。ViewModel 基本都会实现它。

public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

16. ObservableCollection 和 List 的区别?

类型 特点
List<T> 集合变化不会自动通知 UI
ObservableCollection<T> 增删集合项时会通知 UI 刷新

注意: ObservableCollection 只通知集合变化,不通知集合中对象属性变化。对象属性变化还要靠 INotifyPropertyChanged


17. 什么是 ICommand?

用来替代按钮点击事件,适合 MVVM。

核心成员:

  • Execute
  • CanExecute
  • CanExecuteChanged

18. 为什么 MVVM 中推荐用 Command,而不是 Click 事件?

  • 事件会让 View 和代码后置耦合
  • Command 更符合 MVVM,便于测试和维护
  • 按钮是否可用可以通过 CanExecute 自动控制

19. 什么是 MVVM?

职责
Model 数据模型
View 界面
ViewModel 界面逻辑和状态

通过绑定和命令连接 View 与 ViewModel,减少 UI 和业务耦合。


20. MVVM 的优点是什么?

  • 界面和逻辑解耦
  • 更易测试
  • 更易维护
  • 更适合多人协作
  • 符合 WPF 的绑定机制

21. Style、ControlTemplate、DataTemplate 的区别?

类型 作用
Style 设置控件属性、统一外观
ControlTemplate 重定义控件外观结构,不改变数据
DataTemplate 定义数据对象如何显示

一句话记忆:

  • Style 改属性
  • ControlTemplate 改控件长相
  • DataTemplate 改数据展示

22. StaticResource 和 DynamicResource 的区别?

类型 特点
StaticResource 加载时解析,性能更好
DynamicResource 运行时查找,资源变化后可动态更新

一般静态资源优先用 StaticResource


23. Trigger、DataTrigger、EventTrigger 的区别?

类型 触发条件
Trigger 基于控件属性值
DataTrigger 基于绑定数据值
EventTrigger 基于事件,常配合动画

24. Converter 有什么用?

在绑定过程中进行数据转换。

例如:

  • bool -> Visibility
  • 数字 -> 颜色
  • 枚举 -> 文本

接口:

  • IValueConverter
  • IMultiValueConverter

25. ItemsControl、ListBox、ListView 的区别?

控件 特点
ItemsControl 最基础的项控件,只负责显示项
ListBox 支持选择
ListView 更强展示能力,常配合 GridView

26. UserControl 和 CustomControl 的区别?

类型 适用场景
UserControl 快速组合现有控件,适合业务界面
CustomControl 适合做可复用控件库,支持模板和主题

面试标准答法:

  • 业务页面用 UserControl
  • 通用控件库用 CustomControl

27. 什么是模板绑定(TemplateBinding)?

  • ControlTemplate 中绑定到控件自身属性。
  • 比普通绑定更轻量。
  • 常见于自定义控件模板中。

28. WPF 中 UI 线程问题怎么处理?

WPF 大多数 UI 对象只能在创建它的线程访问,通常是主线程。后台线程更新 UI,要通过 Dispatcher 切回 UI 线程。

Dispatcher.Invoke(() => 
{
    txtMessage.Text = "更新UI";
});

29. Dispatcher.Invoke 和 BeginInvoke 的区别?

方法 特点
Invoke 同步执行,会阻塞当前线程
BeginInvoke 异步执行,不阻塞

30. async/await 在 WPF 中有什么注意点?

  • 不要在 UI 线程上用 .Result.Wait(),容易死锁
  • 耗时操作放后台线程
  • await 后默认会回到 UI 同步上下文,所以可以继续更新 UI

31. WPF 中常见内存泄漏原因有哪些?

  • 事件注册后没取消
  • 静态事件
  • 长生命周期对象持有短生命周期对象引用
  • 绑定、计时器、消息订阅没释放
  • 可以用 WeakEventManager 降低事件引用问题

32. WPF 中如何做输入校验?

常见方式:

  • ValidationRule
  • IDataErrorInfo
  • INotifyDataErrorInfo
  • 异常校验 ValidatesOnExceptions=True

现在更推荐 INotifyDataErrorInfo,支持异步和多错误。


33. 什么是资源字典(ResourceDictionary)?

用来存放样式、模板、画刷、字符串等资源。

可放在:

  • App.xaml
  • Window / UserControl
  • 单独 xaml 文件

可通过 MergedDictionaries 合并多个资源文件。


34. WPF 中常见布局控件有哪些?

控件 特点
Grid 最常用,行列布局
StackPanel 横向/纵向堆叠
DockPanel 停靠布局
WrapPanel 自动换行
Canvas 绝对定位
UniformGrid 等分网格

35. Grid 和 StackPanel 怎么选?

  • 复杂界面优先 Grid
  • 简单纵向/横向排列用 StackPanel
  • StackPanel 在滚动、拉伸场景下有时不如 Grid 灵活

36. 什么是视觉虚拟化(UI Virtualization)?

  • 只创建当前可见项的 UI 元素,提升性能。
  • 大数据列表很重要。
  • 常见依赖 VirtualizingStackPanel

37. 如何提高 WPF 性能?

  • 使用 UI 虚拟化
  • 减少视觉树层级
  • 优先 StaticResource
  • 避免频繁刷新整个 UI
  • 大量数据时分页/懒加载
  • 耗时操作异步处理
  • 少用不必要动画和复杂绑定

38. Show 和 ShowDialog 的区别?

方法 特点
Show() 非模态窗口
ShowDialog() 模态窗口,会阻塞当前窗口交互,直到关闭

39. 如何在 WPF 中调试绑定错误?

  • 先看 Output 输出窗口
  • 绑定错误通常会直接输出
  • 常见问题:
    • 属性名拼错
    • DataContext 不对
    • 路径错误
    • 转换器异常

40. WPF 中 Loaded、Initialized、Unloaded 的理解?

事件 说明
Initialized 对象初始化完成
Loaded 控件已加载到可视树,可开始交互
Unloaded 从界面移除时触发

第二部分:C# 核心知识


41. 值类型和引用类型的区别?

类型 特点 举例
值类型 直接存值 intstructboolenum
引用类型 存对象引用 classstring、数组

值类型通常分配在栈/内联,引用类型对象通常在堆上。


42. string 是值类型还是引用类型?

  • string引用类型
  • 但它是不可变的(immutable)

43. string 和 StringBuilder 的区别?

类型 特点
string 不可变,频繁拼接性能差
StringBuilder 适合大量字符串拼接

44. abstract 和 interface 的区别?

对比项 abstract interface
是否可有实现 可以 C# 8.0 前不行
字段 可以有 不可以
构造函数 可以有 不可以
继承 单继承 多实现
语义 “是什么” “能做什么”

45. virtual、override、new 的区别?

关键字 说明
virtual 父类声明可重写
override 子类真正重写
new 隐藏父类成员,不是重写

46. ref 和 out 的区别?

关键字 说明
ref 传入前必须赋值
out 传入前不用赋值,方法内必须赋值

47. 委托和事件的区别?

类型 特点
委托 方法引用类型
事件 对委托的封装,只能订阅/取消,不能直接外部触发

事件更安全,适合发布订阅模式。


48. Func、Action、Predicate 是什么?

类型 说明
Action 无返回值委托
Func 有返回值委托
Predicate<T> 返回 bool 的委托

49. 什么是装箱和拆箱?

  • 装箱:值类型 -> object
  • 拆箱:object -> 值类型
  • 会有性能开销,应尽量避免频繁装拆箱

50. 什么是泛型?有什么好处?

让代码支持多种类型而不牺牲类型安全。

好处:

  • 复用
  • 类型安全
  • 减少装箱拆箱
  • 性能更好

51. using 的作用是什么?

  • 用于命名空间导入
  • 也可用于资源释放,确保调用 Dispose()

52. IDisposable 有什么用?

用来释放非托管资源或重要托管资源。常见如文件流、数据库连接、定时器等。


53. finalizer(析构函数)和 Dispose 的区别?

类型 特点
Dispose 手动、确定性释放
析构函数 GC 不确定时间调用,成本高

推荐优先 Dispose


54. Thread、Task、async/await 的区别?

类型 特点
Thread 底层线程
Task 对异步操作的更高层封装
async/await 简化异步编程语法

现代开发更常用 Task + async/await


55. 什么是死锁?在 UI 中怎么出现?

两个或多个操作互相等待,导致永远卡住。

WPF 常见是 UI 线程里调用异步任务的 .Result/.Wait() 导致死锁。


56. LINQ 的延迟执行是什么意思?

  • 查询语句定义后不立即执行,真正枚举时才执行。
  • WhereSelect 常是延迟执行。
  • ToList()ToArray() 会立即执行。

57. var、dynamic、object 的区别?

类型 特点
var 编译期推断类型,本质仍是强类型
object 所有类型基类,调用成员需强转
dynamic 运行时解析,编译器不过多检查,灵活但不安全

58. == 和 Equals 的区别?

  • ==:默认比较引用,部分类型会重载成值比较
  • Equals:一般用于比较对象逻辑相等性
  • 面试回答要看具体类型实现

第三部分:WPF 高频场景题


59. 为什么界面不刷新?

常见原因:

  • 属性没实现 INotifyPropertyChanged
  • 集合用了 List 而不是 ObservableCollection
  • DataContext 不对
  • 绑定路径写错
  • 后台线程直接更新 UI 导致异常

60. 为什么按钮 CanExecute 改了,但界面没更新?

  • 没触发 CanExecuteChanged
  • 或没调用命令重查询逻辑
  • 若用 RelayCommand,需要主动 RaiseCanExecuteChanged

61. DataGrid/ListBox 数据很多卡顿怎么办?

  • 开启虚拟化
  • 分页加载
  • 减少复杂模板
  • 避免每项都做重计算
  • 不要频繁重设 ItemsSource

62. 为什么 TextBox 改值后,ViewModel 没更新?

  • 绑定模式可能不是 TwoWay
  • UpdateSourceTrigger 可能是 LostFocus
  • 属性没有 set
  • DataContext 不对

63. ObservableCollection 为什么能更新列表,但项内容变化不刷新?

因为它只通知"集合变化",不通知"项属性变化"。每个项对象还需要实现 INotifyPropertyChanged


64. UserControl 中 DataContext 为什么容易出问题?

因为 UserControl 里如果自己设置 DataContext = this,会覆盖外部传入的 DataContext。正确做法:谨慎设置,必要时用 RelativeSource 或依赖属性传值。


65. 什么时候用 DependencyProperty,什么时候用 INotifyPropertyChanged?

场景 选择
控件开发、需要样式/动画/绑定支持 DependencyProperty
ViewModel 属性通知 INotifyPropertyChanged

66. 什么时候用事件,什么时候用命令?

  • MVVM 中优先用 命令
  • 控件内部行为、底层交互、复杂路由事件可用 事件

67. StaticResource 用得好好的,什么时候必须用 DynamicResource?

主题切换、运行时资源变更、皮肤切换等需要动态刷新的场景。


68. 为什么会选择 MVVM?

为了降低 View 和业务逻辑耦合,提高可维护性、可测试性和复用性。


第四部分:面试高频短答速记


69. WPF 绑定失败首先看什么?

Output 输出窗口

70. TextBox.Text 默认绑定模式是什么?

默认 TwoWay,默认 UpdateSourceTrigger 通常是 LostFocus

71. Grid.Row 是什么?

附加属性

72. Button.Click 属于什么事件?

路由事件,一般是 冒泡事件

73. PreviewMouseDown 属于什么事件?

隧道事件(Tunneling)

74. DataTemplate 用于什么?

定义"数据对象怎么显示"。

75. ControlTemplate 用于什么?

定义"控件自己长什么样"。

76. ObservableCollection 是否线程安全?

不是线程安全的。跨线程修改常会报错,需要切回 UI 线程或做同步处理。

77. WPF 中跨线程更新 UI 怎么办?

Dispatcher

78. WPF 中最常见架构模式?

MVVM


第五部分:面试官最爱听的标准短句


1. 为什么用 MVVM?

为了降低 View 和业务逻辑的耦合,提高可维护性、可测试性和复用性。

2. WPF 核心机制有哪些?

数据绑定、依赖属性、路由事件、样式模板、命令机制。

3. 依赖属性有什么用?

让属性能参与绑定、样式、动画和 WPF 属性系统。

4. ObservableCollection 为什么常用?

因为集合增删变化时能自动通知 UI 刷新。

5. WPF 跨线程更新 UI 怎么做?

通过 Dispatcher 切回 UI 线程。

6. 样式和模板区别?

Style 改属性,Template 改结构和外观。

7. 绑定失败怎么看?

先看 Output 窗口的绑定错误信息。


第六部分:15 个必背关键词

  1. MVVM
  2. DataContext
  3. Binding
  4. TwoWay
  5. INotifyPropertyChanged
  6. ObservableCollection
  7. ICommand
  8. DependencyProperty
  9. AttachedProperty
  10. RoutedEvent
  11. Style
  12. ControlTemplate
  13. DataTemplate
  14. Dispatcher
  15. Validation

第七部分:1 分钟自我介绍模板

我主要做 C# 和 WPF 桌面端开发,平时开发中比较常用 MVVM 架构,熟悉数据绑定、命令、依赖属性、路由事件、样式模板、资源字典和异步更新 UI 等内容。项目里也处理过列表性能优化、用户控件封装、输入校验、跨线程 UI 更新等问题。我比较关注代码解耦和可维护性,通常会通过 ViewModel、Command、Converter、ResourceDictionary 等方式优化项目结构。