1. 依赖属性(Dependency Property)与普通属性(CLR属性)的区别?
依赖属性:
通过 DependencyProperty 类注册,支持数据绑定、样式、动画、属性值继承等高级功能。
节省内存:未显式赋值的依赖属性不会占用内存。
支持属性值优先级(如本地值、样式、继承值等)。
示例:
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(Widget), new PropertyMetadata("默认值"));
普通属性:
基于 CLR 的 getter/setter 实现,无内置通知机制,需手动实现 INotifyPropertyChanged 接口支持数据绑定。
适用于简单场景,无需复杂交互或动态更新。
2. 如何自定义依赖属性?
步骤:
public string Value { get { return (string)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); }}public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(Widget));
声明静态 DependencyProperty 字段。
使用 DependencyProperty.Register 方法注册。
通过 CLR 属性包装依赖属性。
3. 用户控件(UserControl)与自定义控件(Custom Control)的区别?
用户控件:
通过组合现有控件实现,适合固定布局的场景(如数据展示卡片)。
前端 XAML 直接定义 UI,后端代码绑定逻辑。
适用场景:快速开发、复用简单 UI 模块。
自定义控件:
继承自 Control 类,需定义控件模板(ControlTemplate)。
支持通过样式和模板高度定制外观,适用复杂交互控件(如自定义按钮、图表)。
示例:
<Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:CustomButton}"> <Border Background="{TemplateBinding Background}" /> </ControlTemplate> </Setter.Value> </Setter>
4. 附加属性(Attached Property)的作用?
用途:允许一个对象为其他对象定义属性(如 Grid.Row)。
定义:
public static readonly DependencyProperty RowProperty = DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid)); public static void SetRow(DependencyObject obj, int value) =>obj.SetValue(RowProperty, value);public static int GetRow(DependencyObject obj) => (int)obj.GetValue(RowProperty);
5. WPF 中的 Page 和 Window 的区别?
Window:传统桌面窗口,独立存在,适合单窗口应用。
Page:用于导航应用(如 Frame 控件内),支持导航历史、生命周期方法(OnNavigatedTo)。
适用场景:
Window:对话框、主界面。
Page:向导式应用、多步骤表单。
6. 样式(Style)与模板(Template)的区别?
样式:通过 Setter 修改控件属性(如颜色、字体),可应用多个属性。
<Setter Property="Background" Value="Red" />
模板:
控件模板(ControlTemplate):完全重写控件外观(如自定义按钮形状)。
数据模板(DataTemplate):定义数据对象的显示方式(如列表项渲染)。
7. 数据绑定(Binding)的常见模式?
单向绑定:{Binding Path=PropertyName, Mode=OneWay}(源目标)。
双向绑定:{Binding Path=PropertyName, Mode=TwoWay}(源目标)。
延迟绑定:适用于异步加载数据(如 Tab 控件内容按需加载)。
// ViewModel 异步加载数据public async Task LoadDataAsync() { await Task.Delay(1000); Data = "Loaded Content";}
8. 路由事件(Routed Event)与命令(Command)的区别?
路由事件:支持冒泡(从子元素向父元素传递)和隧道(父元素向子元素传递)。
// 冒泡事件示例
public static readonly RoutedEvent ClickEvent =
EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyControl));
命令:通过 ICommand 接口实现,解耦 UI 和逻辑(如 RelayCommand)。
public ICommand SaveCommand => new RelayCommand(() => SaveData());
9. 依赖属性与数据绑定的结合示例?
用户控件中绑定依赖属性:
后端代码:
public static readonly DependencyProperty RowProperty = DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid));public static void SetRow(DependencyObject obj, int value) => obj.SetValue(RowProperty, value);public static int GetRow(DependencyObject obj) => (int)obj.GetValue(RowProperty)
总结
WPF 的核心特性(依赖属性、数据绑定、样式/模板)是其灵活性的基础,用户控件适合快速开发,而自定义控件和附加属性则用于复杂场景。理解这些概念能帮助开发高效、可维护的 WPF 应用。
领取专属 10元无门槛券
私享最新 技术干货