程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Windows 8 Store Apps學習(16) 控件基礎: 依賴屬性等等

Windows 8 Store Apps學習(16) 控件基礎: 依賴屬性等等

編輯:關於.NET

控件基礎: 依賴屬性, 附加屬性, 控件的繼承關系, 路由事件和命中測試

介紹

重新想象 Windows 8 Store Apps 之 控件基礎

DependencyProperty - 依賴屬性

AttachedProperty - 附加屬性

控件的繼承關系

路由事件和命中測試

示例

1、開發一個具有 DependencyProperty 和 AttachedProperty 的自定義控件

MyControls/themes/generic.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MyControls">
    
    <!--
        自定義控件的樣式在本文件(themes/generic.xaml)中定義
        
        整合外部 ResourceDictionary
    -->
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ms-appx:///MyControls/themes/MyControl.xaml"/>
    </ResourceDictionary.MergedDictionaries>
       
</ResourceDictionary>

MyControls/themes/MyControl.xaml

<ResourceDiction

ary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MyControls">
    <Style TargetType="local:MyControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:MyControl">
                    <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding 

BorderThickness}">
                        <StackPanel>
                            <!--綁定自定義依賴屬性-->
                            <TextBlock Text="{TemplateBinding Title}" Foreground="White" FontSize="26.667" />
    
                            <!--綁定自定義附加屬性-->
                            <TextBlock Text="{TemplateBinding local:MyAttachedProperty.SubTitle}" Foreground="White" FontSize="14.667" />
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

MyControls/MyControl.cs

/*
 * 開發一個自定義控件,用於演示依賴屬性(Dependency Property)和附加屬性(Attached Property)
 * 
 * 依賴屬性:可以用於樣式, 模板, 綁定, 動畫
 * 附加屬性:全局可用的依賴屬性
 */
    
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml;
    
namespace MyControls
{
    /// <summary>
    /// 用於依賴屬性的演示
    /// </summary>
    public class MyControl : Control
    {
        public MyControl()
        {
            // 指定默認樣式為 typeof(MyControl),即對應:<Style xmlns:local="using:MyControls" TargetType="local: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; // 發生改變之前的值
        }
    }
    
    
    
    /// <summary>
    /// 用於附加屬性的演示
    /// </summary>
    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

<Page
    x:Class="XamlDemo.Controls.Basic.DependencyPropertyDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlDemo.Controls.Basic"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:myControls="using:MyControls"
    mc:Ignorable="d">
    
    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0">
                
            <!--
                演示如何開發和使用自定義依賴屬性(本例所用到的自定義控件請參看:MyControls/MyControl.cs)
            -->
            <myControls:MyControl Background="Blue" BorderBrush="Yellow" BorderThickness="1" Width="100" HorizontalAlignment="Left"
                                  Title="{Binding Value, ElementName=slider}" />
    
            <Slider Name="slider" Width="100" Minimum="0" Maximum="200" IsThumbToolTipEnabled="False"  HorizontalAlignment="Left" />
    
        </StackPanel>
    </Grid>
</Page>

3、演示附加屬性的使用

Controls/Basic/AttachedPropertyDemo.xaml

<Page
    x:Class="XamlDemo.Controls.Basic.AttachedPropertyDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlDemo.Controls.Basic"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:myControls="using:MyControls"
    mc:Ignorable="d">
    
    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0">
    
            <!--
                演示如何開發和使用自定義附加屬性(本例所用到的自定義控件請參看:MyControls/MyControl.cs)
            -->
            <myControls:MyControl Background="Blue" BorderBrush="Yellow" BorderThickness="1" Width="100" HorizontalAlignment="Left"
                                  Title="{Binding Value, ElementName=slider}" myControls:MyAttachedProperty.SubTitle="{Binding Value, ElementName=slider}" />
    
            <Slider Name="slider" Width="100" Minimum="0" Maximum="200" IsThumbToolTipEnabled="False"  HorizontalAlignment="Left" />
                
        </StackPanel>
    </Grid>
</Page>

4、控件的繼承關系的概述

Controls/Basic/Inherit.xaml

<Page
    x:Class="XamlDemo.Controls.Basic.Inherit"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlDemo.Controls.Basic"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    
    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0">
    
            <TextBlock Name="lblMsg" FontSize="14.667" LineHeight="25">
                <Run>繼承關系: FrameworkElement -> UIElement -> 
DependencyObject</Run>
                <LineBreak />
                <Run>DependencyObject - 提供對依賴屬性的訪問,以及獲取此對象關聯的 

CoreDispatcher</Run>
                <LineBreak />
                <Run>UIElement - 可視元素,鍵盤和鼠標輸入等</Run>
                <LineBreak />
                <Run>FrameworkElement - 框架元素,數據綁定,一些公共 API 等。例:Control, 

TextBlock, WebView 等繼承自 FrameworkElement</Run>
                <LineBreak />
                <Run>ContentControl - 其內包含有一個內容,繼承自 Control。例:

ScrollViewer, AppBar 等繼承自 ContentControl</Run>
                <LineBreak />
                <Run>ButtonBase - 按鈕的基本功能,繼承自 ContentControl。例:Button, 

RepeatButton 等繼承自 ButtonBase</Run>
                <LineBreak />
                <Run>ToggleButton - 可切換狀態的按鈕,繼承自 ButtonBase。例:RadioButton, 

CheckBox 等繼承自 ToggleButton</Run>
                <LineBreak />
                <Run>RangeBase - 值在某一范圍內,繼承自 ButtonBase。例:ProgressBar, 

Slider, ScrollBar 等繼承自 RangeBase</Run>
                <LineBreak />
                <Run>ItemsControl - 用於呈現集合,繼承自 Control</Run>
                <LineBreak />
                <Run>Selector - 可選擇集合中的某一項,繼承自 ItemsControl。例:ComboBox, 

ListBox, FlipView, ListViewBase 等繼承自 Selector</Run>
                <LineBreak />
                <Run>ListViewBase - 繼承自 ListViewBase 的控件有 GridView 和 

ListView</Run>
                <LineBreak />
                <Run>Panel - 一個容器,繼承自 FrameworkElement。例:Grid, StackPanel, 

Canvas 等繼承自 Panel</Run>
                <LineBreak />
                <Run>如 ScrollBar, Thumb, RangeBase, ButtonBase, Selector, Popup 等這類基

元控件在 Windows.UI.Xaml.Controls.Primitives 命名空間下</Run>
            </TextBlock>
    
        </StackPanel>
    </Grid>
</Page>

5、路由事件和命中測試

Controls/Basic/RoutedEventDemo.xaml

<Page
    x:Class="XamlDemo.Controls.Basic.RoutedEventDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlDemo.Controls.Basic"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    
    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0">
    
            <Grid HorizontalAlignment="Left" VerticalAlignment="Top">
                <!--
                    演示事件冒泡:兒子傳遞事件給爸爸,爸爸傳遞事件給爺爺,這就是事件冒泡
                -->
                <Border Name="borderRed" Background="Red" Width="300" Height="300">
                    <Border Name="borderGreen" Background="Green" Width="250" Height="250" Tapped="borderGreen_Tapped_1">
                        <Border Name="borderBlue" Background="Blue" Width="200" Height="200" Tapped="borderBlue_Tapped_1">
                            <Border Name="borderOrange" Background="Orange" Width="150" Height="150" Tapped="borderOrange_Tapped_1">
                                <!--命中測試不可見,也就是說 borderPurple 和 borderYellow 均命中測試不可見-->
                                <Border Name="borderPurple" Background="Purple" Width="100" Height="100" Tapped="borderPurple_Tapped_1" IsHitTestVisible="False">
                                    <Border Name="borderYellow" Background="Yellow" Width="50" Height="50" Tapped="borderYellow_Tapped_1" />
                                </Border>
                            </Border>
                        </Border>
                    </Border>
                </Border>
                    
                <!--
                    像這樣排列元素,是沒有事件冒泡的,而只是前面的元素響應事件,後面的元素不會響應事件,也就是說同輩間沒有事件冒泡的概念
                    IsHitTestVisible - 是否對命中測試可見
                    <Rectangle Name="rectangle1" Width="800" Height="400" Fill="Red" />
                    <Rectangle Name="rectangle2" Width="700" Height="350" Fill="Green" />
                    <Rectangle Name="rectangle3" Width="600" Height="300" Fill="Blue" />
                    <Rectangle Name="rectangle4" Width="500" Height="250" Fill="Orange" />
                    <Rectangle Name="rectangle5" Width="400" Height="200" Fill="Purple" />
                -->
            </Grid>
    
            <TextBlock Name="lblMsg" FontSize="14.667" Margin="0 10 0 0" />
    
        </StackPanel>
    </Grid>
</Page>

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

[源碼下載]:http://files.cnblogs.com/webabcd/Windows8.rar

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved