| 
 | 
	
 
 
  [源码下载] 
 
 
 
 
重新想象 Windows 8 Store Apps (16) - 控件基础: 依赖属性, 附加属性, 控件的继承关系, 路由事件和命中测试   
作者:webabcd 
 
介绍 
重新想象 Windows 8 Store Apps 之 控件基础 
 
 
- DependencyProperty - 依赖属性
 
 - AttachedProperty - 附加属性
 
 - 控件的继承关系
 
 - 路由事件和命中测试
 
     
示例 
1、开发一个具有 DependencyProperty 和 AttachedProperty 的自定义控件 
MyControls/themes/generic.xaml 
 
 
 
 
 
 
 
 
 
  MyControls/themes/MyControl.xaml 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  MyControls/MyControl.cs 
 
 
 
/* 
* 开发一个自定义控件,用于演示依赖属性(Dependency Property)和附加属性(Attached Property) 
*  
* 依赖属性:可以用于样式, 模板, 绑定, 动画 
* 附加属性:全局可用的依赖属性 
*/ 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml; 
namespace MyControls 
{ 
///  
/// 用于依赖属性的演示 
///  
public class MyControl : Control 
{ 
public MyControl() 
{ 
// 指定默认样式为 typeof(MyControl),即对应: 
this.DefaultStyleKey = typeof(MyControl); 
} 
// 通过 DependencyObject.GetValue() 和 DependencyObject.SetValue() 访问依赖属性,这里由 Title 属性封装一下,以方便对依赖属性的访问 
public string Title 
{ 
get { return (string)GetValue(TitleProperty); } 
set { SetValue(TitleProperty, value); } 
} 
// 注册一个依赖属性 
public static readonly DependencyProperty TitleProperty = 
DependencyProperty.Register( 
"Title", // 依赖属性的名称 
typeof(string),  // 依赖属性的数据类型 
typeof(MyControl),  // 依赖属性所属的类 
new PropertyMetadata("", PropertyMetadataCallback)); // 指定依赖属性的默认值,以及值发生改变时所调用的方法 
private static void PropertyMetadataCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args) 
{ 
object newValue = args.NewValue; // 发生改变之后的值 
object oldValue = args.OldValue; // 发生改变之前的值 
        } 
} 
 
///  
/// 用于附加属性的演示 
///  
public class MyAttachedProperty 
{ 
// 获取附加属性 
public static string GetSubTitle(DependencyObject obj) 
{ 
return (string)obj.GetValue(SubTitleProperty); 
} 
// 设置附加属性 
public static void SetSubTitle(DependencyObject obj, string value) 
{ 
obj.SetValue(SubTitleProperty, value); 
} 
// 注册一个附加属性 
public static readonly DependencyProperty SubTitleProperty = 
DependencyProperty.RegisterAttached( 
"SubTitle", // 附加属性的名称 
typeof(string), // 附加属性的数据类型 
typeof(MyAttachedProperty), // 附加属性所属的类 
new PropertyMetadata("", PropertyMetadataCallback)); // 指定附加属性的默认值,以及值发生改变时所调用的方法 
private static void PropertyMetadataCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args) 
{ 
object newValue = args.NewValue; // 发生改变之后的值 
object oldValue = args.OldValue; // 发生改变之前的值 
        } 
} 
} 
   
2、演示依赖属性的使用 
Controls/Basic/DependencyPropertyDemo.xaml 
 
 
 
 
 
 
 
 
 
 
 
 
   
3、演示附加属性的使用 
Controls/Basic/AttachedPropertyDemo.xaml 
 
 
 
 
 
 
 
 
 
 
 
 
   
4、控件的继承关系的概述 
Controls/Basic/Inherit.xaml 
 
 
 
 
 
 
 
继承关系: FrameworkElement -> UIElement -> DependencyObject 
 
DependencyObject - 提供对依赖属性的访问,以及获取此对象关联的 CoreDispatcher 
 
UIElement - 可视元素,键盘和鼠标输入等 
 
FrameworkElement - 框架元素,数据绑定,一些公共 API 等。例:Control, TextBlock, WebView 等继承自 FrameworkElement 
 
ContentControl - 其内包含有一个内容,继承自 Control。例:ScrollViewer, AppBar 等继承自 ContentControl 
 
ButtonBase - 按钮的基本功能,继承自 ContentControl。例:Button, RepeatButton 等继承自 ButtonBase 
 
ToggleButton - 可切换状态的按钮,继承自 ButtonBase。例:RadioButton, CheckBox 等继承自 ToggleButton 
 
RangeBase - 值在某一范围内,继承自 ButtonBase。例:ProgressBar, Slider, ScrollBar 等继承自 RangeBase 
 
ItemsControl - 用于呈现集合,继承自 Control 
 
Selector - 可选择集合中的某一项,继承自 ItemsControl。例:ComboBox, ListBox, FlipView, ListViewBase 等继承自 Selector 
 
ListViewBase - 继承自 ListViewBase 的控件有 GridView 和 ListView 
 
Panel - 一个容器,继承自 FrameworkElement。例:Grid, StackPanel, Canvas 等继承自 Panel 
 
如 ScrollBar, Thumb, RangeBase, ButtonBase, Selector, Popup 等这类基元控件在 Windows.UI.Xaml.Controls.Primitives 命名空间下 
 
 
 
 
   
5、路由事件和命中测试 
Controls/Basic/RoutedEventDemo.xaml 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  Controls/Basic/RoutedEventDemo.xaml.cs 
 
 
 
/* 
* 演示路由事件的冒泡和命中测试的可见性 
*  
* TappedRoutedEventArgs 
*     OriginalSource - 引发此路由事件的对象 
*     Handled - 是否将路由事件标记为已处理 
*         true - 不再冒泡 
*         false - 继续冒泡 
*      
* UIElement 
*     IsHitTestVisible - 是否对命中测试可见 
*/ 
using System; 
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml.Input; 
namespace XamlDemo.Controls.Basic 
{ 
public sealed partial class RoutedEventDemo : Page 
{ 
public RoutedEventDemo() 
{ 
this.InitializeComponent(); 
// AddHandler() - 注册一个路由事件,注意最后一个参数:true 代表即使子辈 TappedRoutedEventArgs.Handled = true 也不会影响此元素事件的触发 
// RemoveHandler() - 移除指定的路由事件 
borderRed.AddHandler(UIElement.TappedEvent, new TappedEventHandler(borderRed_Tapped_1), true); 
} 
private void borderRed_Tapped_1(object sender, TappedRoutedEventArgs e) 
{ 
lblMsg.Text += "borderRed tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name; 
lblMsg.Text += Environment.NewLine; 
} 
private void borderGreen_Tapped_1(object sender, TappedRoutedEventArgs e) 
{ 
lblMsg.Text += "borderGreen tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name; 
lblMsg.Text += Environment.NewLine; 
} 
private void borderBlue_Tapped_1(object sender, TappedRoutedEventArgs e) 
{ 
lblMsg.Text += "borderBlue tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name; 
lblMsg.Text += Environment.NewLine; 
// 不会再冒泡,也就是说 borderGreen 无法响应 Tapped 事件,但是 borderRed 注册 Tapped 事件时 handledEventsToo = true,所以 borderRed 会响应 Tapped 事件 
e.Handled = true; 
} 
private void borderOrange_Tapped_1(object sender, TappedRoutedEventArgs e) 
{ 
lblMsg.Text += "borderOrange tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name; 
lblMsg.Text += Environment.NewLine; 
} 
private void borderPurple_Tapped_1(object sender, TappedRoutedEventArgs e) 
{ 
// 不会响应此事件,因为 borderPurple 的 IsHitTestVisible = false 
lblMsg.Text += "borderPurple tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name; 
lblMsg.Text += Environment.NewLine; 
} 
private void borderYellow_Tapped_1(object sender, TappedRoutedEventArgs e) 
{ 
// 不会响应此事件,因为 borderYellow 的爸爸 borderPurple 的 IsHitTestVisible = false 
lblMsg.Text += "borderYellow tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name; 
lblMsg.Text += Environment.NewLine; 
} 
} 
} 
   
OK 
[源码下载] |   
 
 
 
 |