C#之WPF学习之路(2)
目录
控件的父类
DispatcherObject类
DependencyObject类
DependencyObject 类的关键成员和方法
Visual类
Visual 类的主要成员和方法
UIElement类
UIElement 类的主要成员和功能
FrameworkElement类
FrameworkElement 类的主要成员和功能
控件的父类
在 WPF (Windows Presentation Foundation) 框架中,控件的父类们形成了一个层次结构,其中最重要的父类是 DispatcherObject。虽然在整个 .NET 框架中,DispatcherObject 只是居于次要地位,但在 WPF 中却扮演着至关重要的角色,用于处理对象与 Dispatcher 之间的关联,确保 UI 元素的正确更新。
除了 DispatcherObject,WPF 控件的父类们还包括 DependencyObject、Visual、UIElement 和 FrameworkElement。这些父类通过多层次的继承关系,为不同类型的控件提供了各种不同的功能和行为。
控件的继承结构形成了一棵树,使得 WPF 框架具有高度的灵活性和可扩展性,同时也体现了微软工程师们在设计框架时的经典和合理的代码架构。
DispatcherObject类
DispatcherObject 类是 WPF 中非常重要的一个基类,位于 System.Windows.Threading 命名空间中。它的作用是管理对象与 Dispatcher 之间的关联,以确保对象在 UI 线程上正确地进行操作。在 WPF 中,UI 元素必须在创建它们的线程上进行访问和更新,而 DispatcherObject 提供了一种机制来实现这一点。
1、Dispatcher 关联:
- DispatcherObject 类是与 Dispatcher 相关的,Dispatcher 负责管理与线程关联的消息队列。每个 DispatcherObject 都与一个特定的 Dispatcher 实例相关联,通过 Dispatcher 对象可以访问线程相关的上下文信息,以确保对象的操作在正确的线程上执行。
2、线程安全性:
- 由于 DispatcherObject 对象与特定的 UI 线程关联,它们可以确保对象的属性访问和方法调用都在正确的线程上执行,从而避免了多线程并发访问时可能出现的问题,比如线程冲突和资源竞争。
3、UI 元素更新:
- WPF 中的大部分 UI 元素都直接或间接地继承自 DispatcherObject,这使得它们能够在 UI 线程上进行更新,包括属性更改、界面重绘等操作。这样可以确保界面的响应性和一致性。
4、异步操作:
- 通过与 Dispatcher 的关联,DispatcherObject 还提供了一种执行异步操作的机制,可以使用 Dispatcher.Invoke 或 Dispatcher.BeginInvoke 方法来在 UI 线程上执行操作,从而避免了阻塞 UI 线程。
5、应用场景:
- DispatcherObject 主要用于 WPF 中需要与 UI 元素交互的类,比如窗口、控件、动画等。在开发过程中,通常不需要直接实例化 DispatcherObject 类,而是通过继承的方式来间接使用其功能。
总之,DispatcherObject 类的主要责任是管理对象与关联的 Dispatcher 之间的关系,并提供方法来检查和验证访问对象的线程权限。
- 提供对当前 Dispatcher 的访问权限:DispatcherObject 提供了 Dispatcher 属性,该属性允许派生类访问对象所关联的当前 Dispatcher。通过这个属性,派生类可以获得与 UI 线程关联的 Dispatcher 实例,并使用它来在正确的线程上更新 UI 元素。
- 提供线程访问权限的检查和验证:DispatcherObject 提供了 CheckAccess 和 VerifyAccess 方法,用于检查当前线程是否有权访问对象。CheckAccess 方法返回一个布尔值,表示当前线程是否有权访问对象,而 VerifyAccess 方法则在线程无权访问对象时引发异常。通过这两个方法,派生类可以在访问对象之前验证当前线程的访问权限,从而确保对象的访问和更新操作在正确的线程上进行。
DispatcherObject 类通过管理与 Dispatcher 的关联,并提供线程访问权限的检查和验证方法,确保对象的操作在正确的线程上执行,从而保证了 WPF 应用程序的稳定性和性能。
代码示例:
MainWindow.xaml:
MainWindow.xaml.cs:
using System; using System.Threading; using System.Windows; namespace WpfApp2 { /// /// 主窗口.xaml的交互逻辑 /// public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { // 启动一个新线程来执行后台任务 Thread thread = new Thread(BackgroundTask); thread.Start(); } private void BackgroundTask() { // 模拟后台任务 Thread.Sleep(2000); // 在后台线程中更新 UI 元素 Application.Current.Dispatcher.Invoke(() => { // 通过 DispatcherObject 更新 UI 元素 ResultTextBlock.Text = "后台任务已完成"; }); } } }
当用户点击按钮时,将会启动一个后台线程执行后台任务,然后在任务完成后,通过 Dispatcher.Invoke 方法,在 UI 线程上更新 ResultTextBlock 的内容,以显示任务已完成的信息。
DependencyObject类
DependencyObject 是 WPF 中非常重要的基类之一,它提供了一种依赖属性和依赖项之间关联的机制,是 WPF 中实现数据绑定、样式、模板、动画等高级功能的基础。
- 依赖属性:DependencyObject 支持依赖属性的定义和使用。依赖属性是一种特殊类型的属性,它具有与之关联的值,可以通过数据绑定、动画、样式等方式进行设置和获取。依赖属性的一个重要特性是其值可以在不同的元素之间共享和传递,从而实现了数据的自动更新和同步。
- 依赖项:DependencyObject 以及其派生类被称为依赖项,因为它们支持依赖属性,并且能够参与属性值的计算、传递和更新。每个 DependencyObject 实例都维护一个与之关联的属性表,用于存储依赖属性的值和相关的元数据信息。
- 线程安全性:与 DispatcherObject 不同,DependencyObject 并没有与特定的线程关联,因此它的操作并不受 UI 线程的限制。这意味着你可以在任何线程上创建、修改 DependencyObject 的实例,而不必担心线程安全性问题。
- 应用场景:DependencyObject 主要用于 WPF 中的可视化元素,比如窗口、控件、布局容器等。通过使用依赖属性,可以实现诸如绑定、动画、样式等丰富的 UI 功能,使得应用程序的开发变得更加灵活和高效。
- 派生类:除了直接使用 DependencyObject 外,还可以通过创建自定义的派生类来扩展其功能。通过派生类,可以定义自己的依赖属性,并实现与其他 WPF 元素的交互和集成。
总之,DependencyObject 类是 WPF 中实现高级 UI 功能的关键之一,通过支持依赖属性的定义和使用,它为 WPF 应用程序提供了丰富的数据绑定、样式、模板、动画等功能,为开发人员提供了强大的工具和技术来创建现代化、交互式的用户界面。
DependencyObject 类的关键成员和方法
DependencyObject 类的定义包括了一系列方法和属性,其中最常用的是 GetValue 和 SetValue 方法,用于获取和设置依赖属性的值。
以下是 DependencyObject 类的关键成员和方法:
- DependencyObjectType:获取当前 DependencyObject 的 DependencyObjectType 对象,用于表示该对象的类型信息。
- IsSealed:获取一个值,该值指示此 DependencyObject 是否为不可变的。当对象被封闭(sealed)时,其属性不能被修改。
- GetValue(DependencyProperty dp):获取指定依赖属性的值。由于不确定属性值的类型,因此该方法返回一个 object 类型的值。
- SetValue(DependencyProperty dp, object value):设置指定依赖属性的值。第一个参数 dp 表示要设置的依赖属性,第二个参数 value 表示要设置的新值。
- ClearValue(DependencyProperty dp):清除指定依赖属性的值,将其重置为默认值。
- ClearValue(DependencyPropertyKey key):通过提供属性的密钥来清除指定依赖属性的值。
- CoerceValue(DependencyProperty dp):强制重新计算指定依赖属性的值。
- GetLocalValueEnumerator():获取一个枚举器,用于遍历此对象上的所有本地属性值。
- ReadLocalValue(DependencyProperty dp):获取指定依赖属性的本地值。
- SetCurrentValue(DependencyProperty dp, object value):设置依赖属性的当前值,而不影响该属性的原始值。
- OnPropertyChanged(DependencyPropertyChangedEventArgs e):当依赖属性的值发生变化时调用的虚拟方法,用于在派生类中处理属性值更改的通知。
- ShouldSerializeProperty(DependencyProperty dp):确定指定的依赖属性是否应该在序列化时进行持久化。
总之,DependencyObject 类提供了一系列方法和属性,用于管理依赖属性的值,以及处理属性值的变化通知。
代码示例:
MainWindow.xaml:
MainWindow.xaml.cs:
using System.Windows; namespace WpfApp2 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { // 创建 CustomDependencyObject 实例 CustomDependencyObject obj = new CustomDependencyObject(); // 设置依赖属性的值 obj.SetValue(CustomDependencyObject.CustomProperty, "你好,依赖属性!"); // 获取依赖属性的值并显示在消息框中 MessageBox.Show(obj.GetValue(CustomDependencyObject.CustomProperty).ToString()); } } }
CustomDependencyObject.cs:
using System.Windows; namespace WpfApp2 { public class CustomDependencyObject : DependencyObject { // 创建一个依赖属性 public static readonly DependencyProperty CustomProperty = DependencyProperty.Register("Custom", typeof(string), typeof(CustomDependencyObject)); // 属性包装器 public string Custom { get { return (string)GetValue(CustomProperty); } set { SetValue(CustomProperty, value); } } } }
Visual类
Visual 类是 WPF 中表示可视化对象的基类之一,它提供了一种用于呈现和渲染图形元素的机制。Visual 类本身并不直接表示 UI 元素,而是为 UI 元素的呈现提供了基础支持。
以下是关于 Visual 类的详细信息:
- 图形呈现:Visual 类定义了一组基本的图形呈现功能,包括绘制、渲染、布局等。所有可视化对象都可以通过继承 Visual 类来实现自定义的图形呈现逻辑。换句话说,将来我们要学习的Button、TextBox、CheckBox、Gird、ListBox等所有控件都继承自Visual类,控件在绘制到界面的过程中,涉及到转换、裁剪、边框计算等功能,都是使用了Visual父类的功能。
- 基类:Visual 类是所有可视化对象的基类,包括窗口、控件、形状等。通过继承 Visual 类,可以为自定义的可视化对象提供统一的呈现和渲染接口。
- 高性能绘制:Visual 类提供了一种高性能的绘制和渲染机制,可以有效地处理大量的图形元素,并在需要时进行异步渲染和重绘。
- 图形树结构:Visual 类以及其派生类组成了 WPF 中的图形树结构,每个可视化对象都是图形树中的一个节点。通过对图形树的操作,可以实现图形元素的组合、变换、剪裁等操作。
- 布局和排列:Visual 类支持布局和排列功能,可以通过设置位置、大小、旋转等属性来控制图形元素的位置和外观。
- 事件处理:Visual 类支持事件处理机制,可以捕获和处理用户输入、鼠标事件、键盘事件等。
Visual 类的主要成员和方法
Visual 类是 WPF 中的一个核心类,它作为所有可视化对象的基本抽象,提供了许多属性和方法来支持对象的呈现和交互。让我们来看一下 Visual 类的主要成员和方法:
属性:
- VisualParent:获取可视对象的可视化父对象。
- VisualChildrenCount:获取当前对象的子元素数量。
- VisualOffset:获取或设置当前可视对象的偏移量值。
- VisualOpacity:获取或设置可视对象的不透明度。
- VisualEffect:获取或设置要应用于可视对象的位图效果。
- VisualTransform:获取或设置可视对象的变换效果。
其他属性如 VisualYSnappingGuidelines、VisualClip 等,用于控制可视对象的剪裁、缓存模式、边框等。
方法:
- FindCommonVisualAncestor(DependencyObject otherVisual):返回两个可视对象的公共上级。
- IsAncestorOf(DependencyObject descendant):确定可视对象是否为指定对象的上级。
- IsDescendantOf(DependencyObject ancestor):确定可视对象是否为指定对象的后代。
- PointFromScreen(Point point):将屏幕坐标中的点转换为表示当前坐标系的可视对象的坐标。
- PointToScreen(Point point):将表示当前坐标系的可视对象的点转换为屏幕坐标中的点。
- TransformToAncestor(Visual ancestor):返回一个转换,用于将当前可视对象的坐标转换为指定可视对象的坐标。
- TransformToDescendant(Visual descendant):返回一个转换,用于将当前可视对象的坐标转换为指定后代可视对象的坐标。
- TransformToVisual(Visual visual):返回一个转换,用于将当前可视对象的坐标转换为指定可视对象的坐标。
其他方法如 HitTestCore、OnVisualChildrenChanged 等,用于执行命中测试、处理可视对象的子元素变化等。
总之,Visual 类是 WPF 中表示可视化对象的基类,它提供了一种用于呈现和渲染图形元素的基础支持,是实现复杂 UI 功能的关键之一。通过继承 Visual 类,可以实现自定义的可视化对象,并在 WPF 应用程序中实现丰富的图形用户界面。那么,谁又去继承了Visual类? 答案是UIElement类。
UIElement类
UIElement 类是 WPF 中所有用户界面元素的基类,它定义了许多基本的用户界面行为和特性。让我们来了解一下 UIElement 类的特点和功能:
- 呈现和布局:UIElement 类负责定义用户界面元素的呈现和布局。它可以绘制自己的内容,并且可以根据布局算法安排自己的位置和大小。
- 输入事件处理:UIElement 类处理用户输入事件,如鼠标点击、键盘输入、触摸操作等。它定义了一系列方法和事件来响应这些输入事件,比如 MouseDown、MouseUp、KeyDown、KeyUp 等。
- 焦点管理:UIElement 类支持焦点管理,可以接收键盘焦点和鼠标焦点。它定义了一些方法和事件来处理焦点的获取和丢失,如 GotFocus、LostFocus 等。
- 布局变换:UIElement 类可以通过设置 RenderTransform 属性来实现布局的变换,比如旋转、缩放、平移等。
- 命中测试:UIElement 类支持命中测试,用于确定鼠标点击或触摸操作是否命中了该元素。它定义了 HitTest 方法和 IsHitTestVisible 属性来控制命中测试的行为。
- 动画和效果:UIElement 类可以应用动画和效果来改变其外观和行为。它定义了 BeginAnimation 方法和 Effect 属性来支持动画和效果的应用。
- 事件处理:UIElement 类定义了一系列路由事件,可以在元素树中传播和处理。这些事件包括鼠标事件、键盘事件、触摸事件等,以及一些通用的命令事件。
- 可视化树管理:UIElement 类可以组织成可视化树,从而构建用户界面的层次结构。它定义了 Parent 属性和一些方法来管理可视化树的结构。
总之,UIElement 类是 WPF 中所有用户界面元素的基础,它提供了许多基本的用户界面行为和特性,包括呈现、布局、输入事件处理、焦点管理、布局变换、命中测试、动画和效果、事件处理以及可视化树管理等。通过继承 UIElement 类,开发人员可以轻松地创建各种自定义的用户界面元素,并实现丰富的用户界面交互。
UIElement 类的主要成员和功能
UIElement 类是 WPF 中非常重要的一个基类,它继承自 Visual 类,提供了许多用于创建用户界面元素的基本功能。
我们先来看一下这个类的结构定义。
public class UIElement : Visual, IAnimatable, IInputElement { public static readonly RoutedEvent PreviewMouseDownEvent; public static readonly DependencyProperty AreAnyTouchesOverProperty; public static readonly DependencyProperty AreAnyTouchesDirectlyOverProperty; public static readonly DependencyProperty IsKeyboardFocusedProperty; public static readonly DependencyProperty IsStylusCaptureWithinProperty; public static readonly DependencyProperty IsStylusCapturedProperty; public static readonly DependencyProperty IsMouseCaptureWithinProperty; public static readonly DependencyProperty IsMouseCapturedProperty; public static readonly DependencyProperty IsKeyboardFocusWithinProperty; public static readonly DependencyProperty IsStylusOverProperty; public static readonly DependencyProperty IsMouseOverProperty; public static readonly DependencyProperty IsMouseDirectlyOverProperty; public static readonly RoutedEvent TouchLeaveEvent; public static readonly RoutedEvent TouchEnterEvent; public static readonly RoutedEvent LostTouchCaptureEvent; public static readonly RoutedEvent GotTouchCaptureEvent; public static readonly RoutedEvent TouchUpEvent; public static readonly RoutedEvent PreviewTouchUpEvent; public static readonly RoutedEvent TouchMoveEvent; public static readonly RoutedEvent PreviewTouchMoveEvent; public static readonly RoutedEvent TouchDownEvent; public static readonly RoutedEvent PreviewTouchDownEvent; public static readonly RoutedEvent DropEvent; public static readonly RoutedEvent PreviewDropEvent; public static readonly RoutedEvent DragLeaveEvent; public static readonly RoutedEvent PreviewDragLeaveEvent; public static readonly DependencyProperty AreAnyTouchesCapturedProperty; public static readonly DependencyProperty AreAnyTouchesCapturedWithinProperty; public static readonly DependencyProperty AllowDropProperty; public static readonly DependencyProperty RenderTransformProperty; public static readonly RoutedEvent ManipulationCompletedEvent; public static readonly RoutedEvent ManipulationBoundaryFeedbackEvent; public static readonly RoutedEvent ManipulationInertiaStartingEvent; public static readonly RoutedEvent ManipulationDeltaEvent; public static readonly RoutedEvent ManipulationStartedEvent; public static readonly RoutedEvent ManipulationStartingEvent; public static readonly DependencyProperty IsManipulationEnabledProperty; public static readonly DependencyProperty FocusableProperty; public static readonly DependencyProperty IsVisibleProperty; public static readonly DependencyProperty IsHitTestVisibleProperty; public static readonly DependencyProperty IsEnabledProperty; public static readonly DependencyProperty IsFocusedProperty; public static readonly RoutedEvent DragOverEvent; public static readonly RoutedEvent LostFocusEvent; public static readonly DependencyProperty SnapsToDevicePixelsProperty; public static readonly DependencyProperty ClipProperty; public static readonly DependencyProperty ClipToBoundsProperty; public static readonly DependencyProperty VisibilityProperty; public static readonly DependencyProperty UidProperty; public static readonly DependencyProperty CacheModeProperty; public static readonly DependencyProperty BitmapEffectInputProperty; public static readonly DependencyProperty EffectProperty; public static readonly DependencyProperty BitmapEffectProperty; public static readonly DependencyProperty OpacityMaskProperty; public static readonly DependencyProperty OpacityProperty; public static readonly DependencyProperty RenderTransformOriginProperty; public static readonly RoutedEvent GotFocusEvent; public static readonly RoutedEvent PreviewDragOverEvent; public static readonly DependencyProperty IsStylusDirectlyOverProperty; public static readonly RoutedEvent PreviewDragEnterEvent; public static readonly RoutedEvent StylusMoveEvent; public static readonly RoutedEvent PreviewStylusMoveEvent; public static readonly RoutedEvent StylusUpEvent; public static readonly RoutedEvent PreviewStylusUpEvent; public static readonly RoutedEvent StylusDownEvent; public static readonly RoutedEvent PreviewStylusDownEvent; public static readonly RoutedEvent QueryCursorEvent; public static readonly RoutedEvent LostMouseCaptureEvent; public static readonly RoutedEvent GotMouseCaptureEvent; public static readonly RoutedEvent MouseLeaveEvent; public static readonly RoutedEvent MouseEnterEvent; public static readonly RoutedEvent MouseWheelEvent; public static readonly RoutedEvent PreviewStylusInAirMoveEvent; public static readonly RoutedEvent PreviewMouseWheelEvent; public static readonly RoutedEvent PreviewMouseMoveEvent; public static readonly RoutedEvent MouseRightButtonUpEvent; public static readonly RoutedEvent PreviewMouseRightButtonUpEvent; public static readonly RoutedEvent MouseRightButtonDownEvent; public static readonly RoutedEvent PreviewMouseRightButtonDownEvent; public static readonly RoutedEvent DragEnterEvent; public static readonly RoutedEvent PreviewMouseLeftButtonUpEvent; public static readonly RoutedEvent MouseLeftButtonDownEvent; public static readonly RoutedEvent PreviewMouseLeftButtonDownEvent; public static readonly RoutedEvent MouseUpEvent; public static readonly RoutedEvent PreviewMouseUpEvent; public static readonly RoutedEvent MouseDownEvent; public static readonly RoutedEvent MouseMoveEvent; public static readonly RoutedEvent StylusInAirMoveEvent; public static readonly RoutedEvent MouseLeftButtonUpEvent; public static readonly RoutedEvent StylusLeaveEvent; public static readonly RoutedEvent StylusEnterEvent; public static readonly RoutedEvent GiveFeedbackEvent; public static readonly RoutedEvent PreviewGiveFeedbackEvent; public static readonly RoutedEvent QueryContinueDragEvent; public static readonly RoutedEvent TextInputEvent; public static readonly RoutedEvent PreviewTextInputEvent; public static readonly RoutedEvent LostKeyboardFocusEvent; public static readonly RoutedEvent PreviewLostKeyboardFocusEvent; public static readonly RoutedEvent GotKeyboardFocusEvent; public static readonly RoutedEvent PreviewGotKeyboardFocusEvent; public static readonly RoutedEvent KeyUpEvent; public static readonly RoutedEvent PreviewKeyUpEvent; public static readonly RoutedEvent KeyDownEvent; public static readonly RoutedEvent PreviewQueryContinueDragEvent; public static readonly RoutedEvent PreviewStylusButtonUpEvent; public static readonly RoutedEvent PreviewKeyDownEvent; public static readonly RoutedEvent StylusInRangeEvent; public static readonly RoutedEvent PreviewStylusInRangeEvent; public static readonly RoutedEvent StylusOutOfRangeEvent; public static readonly RoutedEvent PreviewStylusSystemGestureEvent; public static readonly RoutedEvent PreviewStylusOutOfRangeEvent; public static readonly RoutedEvent GotStylusCaptureEvent; public static readonly RoutedEvent LostStylusCaptureEvent; public static readonly RoutedEvent StylusButtonDownEvent; public static readonly RoutedEvent StylusButtonUpEvent; public static readonly RoutedEvent PreviewStylusButtonDownEvent; public static readonly RoutedEvent StylusSystemGestureEvent; public UIElement(); public string Uid { get; set; } public Visibility Visibility { get; set; } public bool ClipToBounds { get; set; } public Geometry Clip { get; set; } public bool SnapsToDevicePixels { get; set; } public bool IsFocused { get; } public bool IsEnabled { get; set; } public bool IsHitTestVisible { get; set; } public bool IsVisible { get; } public bool AreAnyTouchesCapturedWithin { get; } public int PersistId { get; } public bool IsManipulationEnabled { get; set; } public bool AreAnyTouchesOver { get; } public bool AreAnyTouchesDirectlyOver { get; } public bool AreAnyTouchesCaptured { get; } public IEnumerable TouchesCaptured { get; } public IEnumerable TouchesCapturedWithin { get; } public IEnumerable TouchesOver { get; } public CacheMode CacheMode { get; set; } public bool Focusable { get; set; } public BitmapEffectInput BitmapEffectInput { get; set; } public bool IsMouseDirectlyOver { get; } public BitmapEffect BitmapEffect { get; set; } public Size RenderSize { get; set; } public bool IsArrangeValid { get; } public bool IsMeasureValid { get; } public Size DesiredSize { get; } public bool AllowDrop { get; set; } public CommandBindingCollection CommandBindings { get; } public InputBindingCollection InputBindings { get; } public bool HasAnimatedProperties { get; } public bool IsMouseOver { get; } public Effect Effect { get; set; } public bool IsStylusOver { get; } public bool IsMouseCaptured { get; } public bool IsMouseCaptureWithin { get; } public bool IsStylusDirectlyOver { get; } public bool IsStylusCaptured { get; } public bool IsStylusCaptureWithin { get; } public bool IsKeyboardFocused { get; } public bool IsInputMethodEnabled { get; } public double Opacity { get; set; } public Brush OpacityMask { get; set; } public bool IsKeyboardFocusWithin { get; } public IEnumerable TouchesDirectlyOver { get; } public Point RenderTransformOrigin { get; set; } public Transform RenderTransform { get; set; } protected StylusPlugInCollection StylusPlugIns { get; } protected virtual bool IsEnabledCore { get; } protected internal virtual bool HasEffectiveKeyboardFocus { get; } public event KeyEventHandler KeyUp; public event EventHandler TouchMove; public event EventHandler PreviewTouchMove; public event EventHandler TouchDown; public event EventHandler PreviewTouchDown; public event DragEventHandler Drop; public event DragEventHandler PreviewDrop; public event DragEventHandler DragLeave; public event DragEventHandler PreviewDragLeave; public event DragEventHandler DragOver; public event DragEventHandler PreviewDragOver; public event DragEventHandler DragEnter; public event DragEventHandler PreviewDragEnter; public event GiveFeedbackEventHandler GiveFeedback; public event GiveFeedbackEventHandler PreviewGiveFeedback; public event QueryContinueDragEventHandler QueryContinueDrag; public event QueryContinueDragEventHandler PreviewQueryContinueDrag; public event TextCompositionEventHandler TextInput; public event EventHandler PreviewTouchUp; public event EventHandler TouchUp; public event EventHandler LostTouchCapture; public event TextCompositionEventHandler PreviewTextInput; public event EventHandler ManipulationInertiaStarting; public event EventHandler ManipulationDelta; public event EventHandler ManipulationStarted; public event EventHandler ManipulationStarting; public event DependencyPropertyChangedEventHandler FocusableChanged; public event DependencyPropertyChangedEventHandler IsVisibleChanged; public event DependencyPropertyChangedEventHandler IsHitTestVisibleChanged; public event DependencyPropertyChangedEventHandler IsEnabledChanged; public event RoutedEventHandler LostFocus; public event EventHandler GotTouchCapture; public event RoutedEventHandler GotFocus; public event DependencyPropertyChangedEventHandler IsKeyboardFocusedChanged; public event DependencyPropertyChangedEventHandler IsStylusCaptureWithinChanged; public event DependencyPropertyChangedEventHandler IsStylusDirectlyOverChanged; public event DependencyPropertyChangedEventHandler IsMouseCaptureWithinChanged; public event DependencyPropertyChangedEventHandler IsMouseCapturedChanged; public event DependencyPropertyChangedEventHandler IsKeyboardFocusWithinChanged; public event DependencyPropertyChangedEventHandler IsMouseDirectlyOverChanged; public event EventHandler TouchLeave; public event EventHandler TouchEnter; public event EventHandler LayoutUpdated; public event KeyboardFocusChangedEventHandler LostKeyboardFocus; public event KeyboardFocusChangedEventHandler PreviewLostKeyboardFocus; public event KeyboardFocusChangedEventHandler GotKeyboardFocus; public event StylusEventHandler PreviewStylusMove; public event StylusEventHandler StylusMove; public event StylusEventHandler PreviewStylusInAirMove; public event StylusEventHandler StylusInAirMove; public event StylusEventHandler StylusEnter; public event StylusEventHandler StylusLeave; public event StylusEventHandler PreviewStylusInRange; public event StylusEventHandler StylusInRange; public event StylusEventHandler PreviewStylusOutOfRange; public event StylusEventHandler StylusOutOfRange; public event StylusSystemGestureEventHandler PreviewStylusSystemGesture; public event StylusSystemGestureEventHandler StylusSystemGesture; public event StylusEventHandler GotStylusCapture; public event StylusEventHandler LostStylusCapture; public event StylusButtonEventHandler StylusButtonDown; public event StylusButtonEventHandler StylusButtonUp; public event StylusButtonEventHandler PreviewStylusButtonDown; public event StylusButtonEventHandler PreviewStylusButtonUp; public event KeyEventHandler PreviewKeyDown; public event KeyEventHandler KeyDown; public event KeyEventHandler PreviewKeyUp; public event StylusEventHandler StylusUp; public event KeyboardFocusChangedEventHandler PreviewGotKeyboardFocus; public event StylusEventHandler PreviewStylusUp; public event StylusDownEventHandler PreviewStylusDown; public event MouseButtonEventHandler PreviewMouseDown; public event MouseButtonEventHandler MouseDown; public event MouseButtonEventHandler PreviewMouseUp; public event MouseButtonEventHandler MouseUp; public event MouseButtonEventHandler PreviewMouseLeftButtonDown; public event MouseButtonEventHandler MouseLeftButtonDown; public event MouseButtonEventHandler PreviewMouseLeftButtonUp; public event MouseButtonEventHandler MouseLeftButtonUp; public event MouseButtonEventHandler PreviewMouseRightButtonDown; public event MouseButtonEventHandler MouseRightButtonDown; public event MouseButtonEventHandler PreviewMouseRightButtonUp; public event MouseButtonEventHandler MouseRightButtonUp; public event MouseEventHandler PreviewMouseMove; public event MouseEventHandler MouseMove; public event MouseWheelEventHandler PreviewMouseWheel; public event MouseWheelEventHandler MouseWheel; public event MouseEventHandler MouseEnter; public event MouseEventHandler MouseLeave; public event MouseEventHandler GotMouseCapture; public event MouseEventHandler LostMouseCapture; public event QueryCursorEventHandler QueryCursor; public event StylusDownEventHandler StylusDown; public event DependencyPropertyChangedEventHandler IsStylusCapturedChanged; public event EventHandler ManipulationCompleted; public event EventHandler ManipulationBoundaryFeedback; public void AddHandler(RoutedEvent routedEvent, Delegate handler); public void AddHandler(RoutedEvent routedEvent, Delegate handler, bool handledEventsToo); public void AddToEventRoute(EventRoute route, RoutedEventArgs e); public void ApplyAnimationClock(DependencyProperty dp, AnimationClock clock, HandoffBehavior handoffBehavior); public void ApplyAnimationClock(DependencyProperty dp, AnimationClock clock); public void Arrange(Rect finalRect); public void BeginAnimation(DependencyProperty dp, AnimationTimeline animation, HandoffBehavior handoffBehavior); public void BeginAnimation(DependencyProperty dp, AnimationTimeline animation); public bool CaptureMouse(); public bool CaptureStylus(); public bool CaptureTouch(TouchDevice touchDevice); public bool Focus(); public object GetAnimationBaseValue(DependencyProperty dp); public IInputElement InputHitTest(Point point); public void InvalidateArrange(); public void InvalidateMeasure(); public void InvalidateVisual(); public void Measure(Size availableSize); public virtual bool MoveFocus(TraversalRequest request); public virtual DependencyObject PredictFocus(FocusNavigationDirection direction); public void RaiseEvent(RoutedEventArgs e); public void ReleaseAllTouchCaptures(); public void ReleaseMouseCapture(); public void ReleaseStylusCapture(); public bool ReleaseTouchCapture(TouchDevice touchDevice); public void RemoveHandler(RoutedEvent routedEvent, Delegate handler); public bool ShouldSerializeCommandBindings(); public bool ShouldSerializeInputBindings(); public Point TranslatePoint(Point point, UIElement relativeTo); public void UpdateLayout(); protected virtual void ArrangeCore(Rect finalRect); protected virtual Geometry GetLayoutClip(Size layoutSlotSize); protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters); protected override GeometryHitTestResult HitTestCore(GeometryHitTestParameters hitTestParameters); protected virtual Size MeasureCore(Size availableSize); protected virtual void OnAccessKey(AccessKeyEventArgs e); protected virtual void OnChildDesiredSizeChanged(UIElement child); protected virtual AutomationPeer OnCreateAutomationPeer(); protected virtual void OnDragEnter(DragEventArgs e); protected virtual void OnDragLeave(DragEventArgs e); protected virtual void OnDragOver(DragEventArgs e); protected virtual void OnDrop(DragEventArgs e); protected virtual void OnGiveFeedback(GiveFeedbackEventArgs e); protected virtual void OnGotFocus(RoutedEventArgs e); protected virtual void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e); protected virtual void OnGotMouseCapture(MouseEventArgs e); protected virtual void OnGotStylusCapture(StylusEventArgs e); protected virtual void OnGotTouchCapture(TouchEventArgs e); protected virtual void OnIsKeyboardFocusedChanged(DependencyPropertyChangedEventArgs e); protected virtual void OnIsKeyboardFocusWithinChanged(DependencyPropertyChangedEventArgs e); protected virtual void OnIsMouseCapturedChanged(DependencyPropertyChangedEventArgs e); protected virtual void OnIsMouseCaptureWithinChanged(DependencyPropertyChangedEventArgs e); protected virtual void OnIsMouseDirectlyOverChanged(DependencyPropertyChangedEventArgs e); protected virtual void OnIsStylusCapturedChanged(DependencyPropertyChangedEventArgs e); protected virtual void OnIsStylusCaptureWithinChanged(DependencyPropertyChangedEventArgs e); protected virtual void OnIsStylusDirectlyOverChanged(DependencyPropertyChangedEventArgs e); protected virtual void OnKeyDown(KeyEventArgs e); protected virtual void OnKeyUp(KeyEventArgs e); protected virtual void OnLostFocus(RoutedEventArgs e); protected virtual void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e); protected virtual void OnLostMouseCapture(MouseEventArgs e); protected virtual void OnLostStylusCapture(StylusEventArgs e); protected virtual void OnLostTouchCapture(TouchEventArgs e); protected virtual void OnManipulationBoundaryFeedback(ManipulationBoundaryFeedbackEventArgs e); protected virtual void OnManipulationCompleted(ManipulationCompletedEventArgs e); protected virtual void OnManipulationDelta(ManipulationDeltaEventArgs e); protected virtual void OnManipulationInertiaStarting(ManipulationInertiaStartingEventArgs e); protected virtual void OnManipulationStarted(ManipulationStartedEventArgs e); protected virtual void OnManipulationStarting(ManipulationStartingEventArgs e); protected virtual void OnMouseDown(MouseButtonEventArgs e); protected virtual void OnMouseEnter(MouseEventArgs e); protected virtual void OnMouseLeave(MouseEventArgs e); protected virtual void OnMouseLeftButtonDown(MouseButtonEventArgs e); protected virtual void OnMouseLeftButtonUp(MouseButtonEventArgs e); protected virtual void OnMouseMove(MouseEventArgs e); protected virtual void OnMouseRightButtonDown(MouseButtonEventArgs e); protected virtual void OnMouseRightButtonUp(MouseButtonEventArgs e); protected virtual void OnMouseUp(MouseButtonEventArgs e); protected virtual void OnMouseWheel(MouseWheelEventArgs e); protected virtual void OnPreviewDragEnter(DragEventArgs e); protected virtual void OnPreviewDragLeave(DragEventArgs e); protected virtual void OnPreviewDragOver(DragEventArgs e); protected virtual void OnPreviewDrop(DragEventArgs e); protected virtual void OnPreviewGiveFeedback(GiveFeedbackEventArgs e); protected virtual void OnPreviewGotKeyboardFocus(KeyboardFocusChangedEventArgs e); protected virtual void OnPreviewKeyDown(KeyEventArgs e); protected virtual void OnPreviewKeyUp(KeyEventArgs e); protected virtual void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e); protected virtual void OnPreviewMouseDown(MouseButtonEventArgs e); protected virtual void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e); protected virtual void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e); protected virtual void OnPreviewMouseMove(MouseEventArgs e); protected virtual void OnPreviewMouseRightButtonDown(MouseButtonEventArgs e); protected virtual void OnPreviewMouseRightButtonUp(MouseButtonEventArgs e); protected virtual void OnPreviewMouseUp(MouseButtonEventArgs e); protected virtual void OnPreviewMouseWheel(MouseWheelEventArgs e); protected virtual void OnPreviewQueryContinueDrag(QueryContinueDragEventArgs e); protected virtual void OnPreviewStylusButtonDown(StylusButtonEventArgs e); protected virtual void OnPreviewStylusButtonUp(StylusButtonEventArgs e); protected virtual void OnPreviewStylusDown(StylusDownEventArgs e); protected virtual void OnPreviewStylusInAirMove(StylusEventArgs e); protected virtual void OnPreviewStylusInRange(StylusEventArgs e); protected virtual void OnPreviewStylusMove(StylusEventArgs e); protected virtual void OnPreviewStylusOutOfRange(StylusEventArgs e); protected virtual void OnPreviewStylusSystemGesture(StylusSystemGestureEventArgs e); protected virtual void OnPreviewStylusUp(StylusEventArgs e); protected virtual void OnPreviewTextInput(TextCompositionEventArgs e); protected virtual void OnPreviewTouchDown(TouchEventArgs e); protected virtual void OnPreviewTouchMove(TouchEventArgs e); protected virtual void OnPreviewTouchUp(TouchEventArgs e); protected virtual void OnQueryContinueDrag(QueryContinueDragEventArgs e); protected virtual void OnQueryCursor(QueryCursorEventArgs e); protected virtual void OnRender(DrawingContext drawingContext); protected virtual void OnStylusButtonDown(StylusButtonEventArgs e); protected virtual void OnStylusButtonUp(StylusButtonEventArgs e); protected virtual void OnStylusDown(StylusDownEventArgs e); protected virtual void OnStylusEnter(StylusEventArgs e); protected virtual void OnStylusInAirMove(StylusEventArgs e); protected virtual void OnStylusInRange(StylusEventArgs e); protected virtual void OnStylusLeave(StylusEventArgs e); protected virtual void OnStylusMove(StylusEventArgs e); protected virtual void OnStylusOutOfRange(StylusEventArgs e); protected virtual void OnStylusSystemGesture(StylusSystemGestureEventArgs e); protected virtual void OnStylusUp(StylusEventArgs e); protected virtual void OnTextInput(TextCompositionEventArgs e); protected virtual void OnTouchDown(TouchEventArgs e); protected virtual void OnTouchEnter(TouchEventArgs e); protected virtual void OnTouchLeave(TouchEventArgs e); protected virtual void OnTouchMove(TouchEventArgs e); protected virtual void OnTouchUp(TouchEventArgs e); protected internal virtual DependencyObject GetUIParentCore(); protected internal virtual void OnRenderSizeChanged(SizeChangedInfo info); protected internal override void OnVisualParentChanged(DependencyObject oldParent); }
下面是 UIElement 类的主要成员和功能:
属性:
- IsHitTestVisible:获取或设置一个值,该值指示在命中测试过程中此元素是否可见。如果设置为 false,则该元素不会参与命中测试。
- Opacity:获取或设置此元素的不透明度。值为 1.0 表示完全不透明,值为 0.0 表示完全透明。
- RenderTransform:获取或设置一个转换,该转换在呈现此元素时应用于该元素。
- RenderTransformOrigin:获取或设置用于呈现此元素的任何呈现转换的中心点。
- Visibility:获取或设置此元素在用户界面中的可见性状态。可见性状态可以是 Visible、Collapsed 或 Hidden。
方法:
- CaptureMouse():捕获鼠标,使此元素接收鼠标事件,即使鼠标指针已移出元素的边界。
- ReleaseMouseCapture():释放先前由此元素捕获的鼠标。
事件:
- MouseDown、MouseUp:鼠标按下和释放事件。
- MouseEnter、MouseLeave:鼠标进入和离开事件。
- MouseMove:鼠标移动事件。
- GotFocus、LostFocus:元素获得和失去焦点事件。
命中测试:
- HitTestVisibility 属性和 HitTestBounds 方法用于执行命中测试,判断鼠标点击是否命中该元素。
- 输入事件处理:
- PreviewKeyDown、KeyDown、PreviewKeyUp、KeyUp 事件用于处理键盘输入。
- PreviewMouseDown、MouseDown、PreviewMouseUp、MouseUp、PreviewMouseMove、MouseMove 等事件用于处理鼠标输入。
布局和渲染:
- Measure(Size availableSize) 和 Arrange(Rect finalRect) 方法用于计算元素的大小和位置。
- InvalidateMeasure() 和 InvalidateArrange() 方法用于标记元素的布局无效,需要重新计算。
焦点管理:
- Focus() 方法用于将焦点设置到该元素上。
- IsFocused 属性表示该元素是否具有焦点。
总之,UIElement 类提供了许多基本的用户界面功能,包括输入事件处理、命中测试、布局和渲染、焦点管理等。通过继承 UIElement 类,可以创建各种自定义的用户界面元素,并实现丰富的用户界面交互。
代码示例:
using System.Windows; namespace WpfApp2 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } // 在代码中使用 Button,它是 UIElement 的子类 private void myButton_Click(object sender, RoutedEventArgs e) { MessageBox.Show("按钮点击了!"); } } }
FrameworkElement类
FrameworkElement 是 WPF 中控件体系的核心基类之一,它继承自 UIElement,而 UIElement 是更基础的用户界面元素基类,提供了诸如输入事件、布局和呈现等基本功能。继承关系是:Object->DispatcherObject->DependencyObject->Visual->UIElement->FrameworkElement。
在 FrameworkElement 基类之上,控件体系开始分支,形成三个主要方向:
- Shape 图形类:这个方向包括一系列的形状类,如 Rectangle、Ellipse、Polygon 等,它们继承自 Shape 类,Shape 类继承自 FrameworkElement,因此它们具有 FrameworkElement 的所有功能,同时还有特定于形状的属性和方法。
- Control 控件类:这个方向包括一系列的用户界面控件类,如 Button、TextBox、ComboBox 等,它们继承自 Control 类,Control 类继承自 FrameworkElement,因此它们也具有 FrameworkElement 的所有功能,同时还有特定于控件的属性和方法。
- Panel 布局类:这个方向包括一系列的布局容器类,如 StackPanel、Grid、Canvas 等,它们继承自 Panel 类,Panel 类继承自 FrameworkElement,因此它们也具有 FrameworkElement 的所有功能,同时还有特定于布局的属性和方法。
根据官方文档,FrameworkElement 在 WPF 框架中具有以下主要功能和责任:
- 布局系统定义:FrameworkElement 提供了特定于 WPF 框架级别的布局系统实现,包括为派生类提供替代布局方法的密封方法。例如,FrameworkElement 提供了 ArrangeOverride 方法,用于派生类重写以提供自定义的排列逻辑。这些更改反映了在 WPF 框架级别存在一个完整的布局系统,可以呈现任何 FrameworkElement 派生类。
- 逻辑树:FrameworkElement 支持将元素树表示为逻辑树,并支持在标记中定义该树。然而,FrameworkElement 故意不定义内容模型,而是将该责任留给派生类。
- 对象生存期事件:FrameworkElement 定义了多个与对象生存期相关的事件,例如 Initialized、Loaded 和 Unloaded 事件。这些事件提供了在元素初始化或加载到逻辑树中时执行代码的挂钩。
- 支持数据绑定和动态资源引用:FrameworkElement 实现了解析存储为表达式的成员值的能力,这对于支持数据绑定和动态资源引用非常重要。数据绑定和资源的属性级支持由 DependencyProperty 类实现,并在属性系统中体现。
- 风格:FrameworkElement 定义了 Style 属性,用于应用样式。但是,它并未定义对模板的支持或支持修饰符。这些功能通常由控件类引入,如 Control 和 ContentControl。
- 更多动画支持:FrameworkElement 通过实现 BeginStoryboard 等成员扩展了某些动画支持,使得在界面元素上可以更方便地应用动画效果。
总之,FrameworkElement 在 WPF 框架中承担了多项重要责任,包括布局系统的实现、逻辑树的管理、对象生存期事件的处理、数据绑定和动态资源引用的支持、样式应用以及动画支持等。这些功能使得 FrameworkElement 成为 WPF 控件体系中的核心基类之一。
FrameworkElement 类的主要成员和功能
属性分析:
1. LayoutTransform 属性:LayoutTransform 属性用于在执行布局时应用于元素的图形转换。与 RenderTransform 属性不同,LayoutTransform 在布局时应用,而 RenderTransform 在布局后应用。通常建议使用 RenderTransform,因为它的性能更好。
2. Width 和 Height 属性:Width 和 Height 属性分别表示控件的宽度和高度。ActualWidth 和 ActualHeight 属性表示控件的实际呈现宽度和高度,而 MaxWidth 和 MinWidth、MaxHeight 和 MinHeight 属性用于设置控件的最大和最小宽度和高度限制。
3. Tag 属性:Tag 属性用于在控件上存储任意对象。它是一个 object 类型的属性,可用于临时存储与控件相关的数据。
4. Name 属性:Name 属性用于设置控件的标识名称,在 XAML 中引用控件时会使用到。
5. Margin 属性:Margin 属性用于设置控件的外边距,指定控件与其容器边界之间的间距。
6. Padding 属性:Padding 属性用于设置控件的内边距,指定控件内容与其边界之间的间距。但是需要注意的是,Padding 属性属于 Control 类,而不是 FrameworkElement 类。
7. HorizontalAlignment 和 VerticalAlignment 属性:HorizontalAlignment 属性和 VerticalAlignment 属性分别用于设置控件在水平和垂直方向上的对齐方式。它们都是枚举类型,包括 Left、Center、Right、Stretch 等值。
8. ToolTip 属性:ToolTip 属性用于设置控件的工具提示内容,在鼠标悬停在控件上时显示。
9. Parent 属性:Parent 属性用于获取控件的逻辑父元素,即该控件所在的容器。
10. Style 和 FocusVisualStyle 属性:Style 属性用于设置控件的样式,而 FocusVisualStyle 属性用于设置控件在获得焦点时的样式。
11. Resources 属性:Resources 属性用于设置控件本地定义的资源字典,其中包含控件使用的资源。
12. DataContext 属性:DataContext 属性用于设置控件的数据上下文,用于实现数据绑定。
13. ContextMenu 属性:ContextMenu 属性用于设置控件的上下文菜单。
14. Cursor 属性:Cursor 属性用于设置控件在鼠标指针位于其上时显示的光标形状。
事件分析:
FrameworkElement 类提供了多个事件,其中比较常用的包括:
1. Initialized 事件:在元素初始化完成后引发。
2. Loaded 事件:在元素被加载到视觉树中并准备呈现时引发。
3. Unloaded 事件:在元素从视觉树中移除后引发。
4. SizeChanged 事件:在元素的大小发生变化时引发。
方法成员:
FrameworkElement 类还提供了一些方法成员,比如 FindName、FindResource、TryFindResource、SetBinding 等,用于在代码中查找元素、资源以及进行数据绑定等操作。
我们来看一下哪些类会继承这个FrameworkElement基类:
Microsoft.Windows.Themes.BulletChrome
Microsoft.Windows.Themes.ScrollChrome
System.Windows.Controls.AccessText
System.Windows.Controls.AdornedElementPlaceholder
System.Windows.Controls.ContentPresenter
System.Windows.Controls.Control
System.Windows.Controls.Decorator
System.Windows.Controls.Image
System.Windows.Controls.InkCanvas
System.Windows.Controls.ItemsPresenter
System.Windows.Controls.MediaElement
System.Windows.Controls.Page
System.Windows.Controls.Panel
System.Windows.Controls.Primitives.DocumentPageView
System.Windows.Controls.Primitives.GridViewRowPresenterBase
System.Windows.Controls.Primitives.Popup
System.Windows.Controls.Primitives.TickBar
System.Windows.Controls.Primitives.Track
System.Windows.Controls.TextBlock
System.Windows.Controls.ToolBarTray
System.Windows.Controls.Viewport3D
System.Windows.Documents.Adorner
System.Windows.Documents.AdornerLayer
System.Windows.Documents.DocumentReference
System.Windows.Documents.FixedPage
System.Windows.Documents.Glyphs
System.Windows.Documents.PageContent
System.Windows.Interop.HwndHost
System.Windows.Shapes.Shape代码示例:
using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace WpfApp2 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { // 设置按钮的外边距 myButton.Margin = new Thickness(20); // 设置按钮的背景颜色 myButton.Background = Brushes.LightBlue; // 设置按钮的宽度 myButton.Width = 150; // 获取按钮的实际宽度 double actualWidth = myButton.ActualWidth; // 获取按钮的逻辑父元素 DependencyObject parent = myButton.Parent; // 查找名为 "myButton" 的元素 FrameworkElement? foundElement = this.FindName("myButton") as FrameworkElement; // 注册名为 "myButton2" 的元素 FrameworkElement button2 = new Button(); button2.Name = "myButton2"; this.RegisterName(button2.Name, button2); } } }
- DispatcherObject 主要用于 WPF 中需要与 UI 元素交互的类,比如窗口、控件、动画等。在开发过程中,通常不需要直接实例化 DispatcherObject 类,而是通过继承的方式来间接使用其功能。
- 通过与 Dispatcher 的关联,DispatcherObject 还提供了一种执行异步操作的机制,可以使用 Dispatcher.Invoke 或 Dispatcher.BeginInvoke 方法来在 UI 线程上执行操作,从而避免了阻塞 UI 线程。
- WPF 中的大部分 UI 元素都直接或间接地继承自 DispatcherObject,这使得它们能够在 UI 线程上进行更新,包括属性更改、界面重绘等操作。这样可以确保界面的响应性和一致性。
- 由于 DispatcherObject 对象与特定的 UI 线程关联,它们可以确保对象的属性访问和方法调用都在正确的线程上执行,从而避免了多线程并发访问时可能出现的问题,比如线程冲突和资源竞争。