田敏
返回博客列表
WPF

WPF 基础知识

田敏
2025-10-203 分钟阅读
WPFC#

🧱 WPF 面试题与标准答案汇总


一、基础篇

1️⃣ WPF 与 WinForms 的区别

答案:

  • 渲染机制不同:WPF 基于 DirectX 硬件加速渲染;WinForms 基于 GDI+。
  • 布局系统不同:WPF 使用自适应布局(Layout System),WinForms 采用固定坐标。
  • 样式与模板:WPF 支持 StyleControlTemplateDataTemplate 实现完全外观分离。
  • 数据绑定能力强:内置 Binding 系统,支持 INotifyPropertyChanged
  • 分层设计:逻辑树 + 视觉树;WinForms 没有。
  • 声明式 UI:XAML 分离界面与逻辑代码,利于 MVVM。

2️⃣ 什么是 XAML?

答案:

  • XAML(Extensible Application Markup Language)是 WPF 的界面标记语言
  • 它是 XML 格式,用于定义对象、属性与层级结构。
  • 编译时会转化为对应的 .NET 对象(如 ButtonGrid)。
  • 优势:界面与逻辑分离、可设计性强、支持数据绑定。

3️⃣ 依赖属性(DependencyProperty)

答案:

  • 是继承自 DependencyObject 的特殊属性,用于支持:

    • 数据绑定(Binding)
    • 样式与动画(Style、Animation)
    • 属性值继承
  • 定义方式:

    public static readonly DependencyProperty IsOpenProperty =
        DependencyProperty.Register("IsOpen", typeof(bool), typeof(MyControl),
            new PropertyMetadata(false, OnIsOpenChanged));
    public bool IsOpen
    {
        get => (bool)GetValue(IsOpenProperty);
        set => SetValue(IsOpenProperty, value);
    }
    
  • PropertyChangedCallback 用于监听变化,CoerceValueCallback 可限制取值。


4️⃣ 路由事件(RoutedEvent)

答案:

  • WPF 的事件系统支持路由机制
    • 冒泡 (Bubble):事件从子控件向父控件传递。
    • 隧道 (Tunnel):事件从根节点向子控件传递。
    • 直接 (Direct):不路由,仅当前控件响应。
  • 例:
    • PreviewMouseDown → 隧道事件
    • MouseDown → 冒泡事件

5️⃣ 数据绑定 (Data Binding)

答案:

  • 是 WPF 最核心机制之一。
  • 绑定公式:Binding Source → Target
  • 关键属性:
    • Path:绑定路径
    • Mode:绑定方向(OneWay、TwoWay、OneTime、OneWayToSource)
    • UpdateSourceTrigger:更新触发时机(默认 LostFocus
  • 需实现接口 INotifyPropertyChanged 来通知 UI 更新。

二、样式与资源篇

6️⃣ Style 与 Template 的区别

答案:

| 特性 | Style | Template | | -------- | ---------------------------------- | ---------------------------------------- | | 作用 | 修改现有控件属性 | 彻底重定义控件外观 | | 应用方式 | Style="{StaticResource MyStyle}" | Template="{StaticResource MyTemplate}" | | 触发器 | 可使用 TriggerDataTrigger | 可在模板中定义 VisualState | | 示例 | 改字体、颜色 | 重绘一个按钮的形状 |


7️⃣ StaticResource 与 DynamicResource 区别

答案:

  • StaticResource:在加载时解析,性能高但不能动态变化。
  • DynamicResource:在运行时动态解析,可响应主题变化。
  • 使用建议:一般样式用 Static,主题相关资源用 Dynamic。

8️⃣ 资源查找顺序

答案:

  1. 控件本地资源 (FrameworkElement.Resources)
  2. 父元素资源
  3. 应用程序级资源 (Application.Resources)
  4. 主题资源
  5. 系统资源(如系统颜色)

三、架构与 MVVM 篇

9️⃣ MVVM 模式原理

答案:

  • Model:业务数据层(实体、数据逻辑)
  • ViewModel:逻辑层(属性、命令、状态)
  • View:界面层(XAML、绑定 ViewModel)
  • 优势:
    • 解耦 UI 与逻辑
    • 易于测试
    • 数据绑定自动同步 UI 与数据状态

🔟 ICommand 与命令绑定

答案:

  • 命令模式让 UI 操作与逻辑解耦。

  • 实现:

    public class RelayCommand : ICommand
    {
        private readonly Action _execute;
        private readonly Func<bool> _canExecute;
        public RelayCommand(Action execute, Func<bool> canExecute = null) 
        { _execute = execute; _canExecute = canExecute; }
    
        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object _) => _canExecute?.Invoke() ?? true;
        public void Execute(object _) => _execute();
    }
    
  • 在 XAML 中绑定:

    <Button Command="{Binding SaveCommand}" Content="保存"/>
    

11️⃣ Prism 框架核心

答案:

  • DelegateCommand:简化命令实现。
  • EventAggregator:跨模块通信。
  • RegionManager:实现模块化导航。
  • Dependency Injection:通过容器(Unity、DryIoc)实现解耦。

四、性能与优化篇

12️⃣ 虚拟化 (Virtualization)

答案:

  • 用于优化大数据列表性能。

  • 只渲染可见区域的元素。

  • ItemsControlListViewDataGrid 可启用虚拟化:

    <ListView VirtualizingPanel.IsVirtualizing="True"
              VirtualizingPanel.VirtualizationMode="Recycling" />
    

13️⃣ 如何优化 WPF 性能

答案:

  • 启用 UI 虚拟化。
  • 避免频繁修改 UI 元素。
  • 使用 Freezable 对象(如 Brush)冻结后可提高渲染效率。
  • 使用 BitmapCache 缓存复杂视觉。
  • 优化绑定数量,避免绑定循环。
  • 使用 BindingBase.IsAsync = true 异步绑定大数据。

14️⃣ 内存泄漏排查

答案:

  • 常见原因:
    • 事件未解绑(尤其是静态事件)
    • 未关闭绑定或动画
    • 使用 DispatcherTimer 忘记停止
  • 工具:
    • Visual Studio Diagnostic Tools
    • .NET Memory Profiler
    • Snoop、WPF Inspector

五、项目与实战篇

15️⃣ 自定义控件与 UserControl 区别

答案:

| 类型 | 特点 | 适用场景 | | ------------- | -------------------------------- | ---------------------- | | UserControl | 组合多个现有控件 | 简单封装,快速开发 | | CustomControl | 继承 Control,通过模板定义外观 | 可复用、支持样式与主题 |


16️⃣ 动态主题切换实现

答案:

Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(
    new ResourceDictionary { Source = new Uri("Themes/Dark.xaml", UriKind.Relative) });

或使用 Prism 的 ThemeService 管理。


17️⃣ 如何在后台线程更新 UI

答案:

  • 只能在 UI 线程访问控件。

  • 方法:

    Application.Current.Dispatcher.Invoke(() =>
    {
        myTextBlock.Text = "更新成功";
    });
    
  • 或使用数据绑定 + ObservableCollection 自动刷新。


18️⃣ 常见 WPF 调试技巧

答案:

  • 查看绑定错误:在输出窗口中启用 PresentationTraceSources.TraceLevel=High
  • 使用工具:Snoop、WPF Inspector 查看可视树
  • ShowVisualTree() 调试模板和样式

🏁 加分题

19️⃣ WPF 的视觉树与逻辑树区别

答案:

  • 逻辑树:反映对象层级关系(如 Window → Grid → Button)
  • 视觉树:包含视觉元素与渲染细节(如 Border、ContentPresenter)
  • 用途:
    • 逻辑树用于资源查找、事件路由。
    • 视觉树用于渲染与模板分析。

20️⃣ WPF、Avalonia、WinUI 比较

| 框架 | 渲染引擎 | 平台支持 | 特点 | | -------- | --------------- | ---------------------- | -------------------- | | WPF | DirectX | Windows | 成熟、丰富的控件体系 | | Avalonia | Skia | 跨平台 (Win/Linux/Mac) | MVVM 兼容好 | | WinUI 3 | Windows App SDK | Windows 10+ | UWP 风格、现代化外观 |


版权协议:MIT返回列表