• 背水一战 Windows 10 (76)


    [源码下载]


    背水一战 Windows 10 (76) - 控件(控件基类): Control - 基础知识, 焦点相关, 运行时获取 ControlTemplate 和 DataTemplate 中的元素



    作者:webabcd


    介绍
    背水一战 Windows 10 之 控件(控件基类 - Control)

    • 基础知识
    • 焦点相关
    • 运行时获取 ControlTemplate 和 DataTemplate 中的元素



    示例
    1、演示 Control 的基础知识
    Controls/BaseControl/ControlDemo/Demo1.xaml

    <Page
        x:Class="Windows10.Controls.BaseControl.ControlDemo.Demo1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows10.Controls.BaseControl.ControlDemo"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="Orange">
    
            <TextBox Name="textBox" Text="i am webabcd" TextWrapping="Wrap" AcceptsReturn="True" Margin="100" />
    
        </Grid>
    </Page>

    Controls/BaseControl/ControlDemo/Demo1.xaml.cs

    /*
     * Control - Control(继承自 UIElement, 请参见 /Controls/BaseControl/FrameworkElementDemo/)
     *     Background - 背景 Brush
     *     Foreground - 前景 Brush
     *     BorderBrush - 边框 Brush
     *     BorderThickness - 边框 Thickness
     *     Padding - Padding
     *     FontSize - 字号大小(单位:像素)
     *     FontFamily - 首选字体,多个用“,”分隔,找不到第 1 个就用第 2 个,找不到第 2 个就用第 3 个,以此类推
     *     FontStretch - 字体的拉伸值(FontStretch 枚举),默认值是 Normal(大部分字体都不支持这个属性)
     *     FontStyle - 字体样式(FontStyle 枚举)
     *         Normal - 默认值
     *         Italic - 使用字体自带的斜体
     *         Oblique - 通过程序让正常字体倾斜(对于自身不带斜体的字体可以使用此值让字体倾斜)
     *     FontWeight - 字体粗细(FontWeights 实体类),默认值是 Normal
     *     CharacterSpacing - 用于设置字符间距
     *         具体字符间隔像素计算公式如下:字体大小 * CharacterSpacing值 / 1000 = 字符间距像素值
     *     IsTextScaleFactorEnabled - 是否启用文本自动放大功能(默认值是 true)
     *         在“设置”->“轻松使用”中可以调整文本缩放大小,IsTextScaleFactorEnabled 就是用于决定 TextBlock 显示的文本是否跟着这个设置走
     *     HorizontalContentAlignment - 内容的水平对齐方式
     *     VerticalContentAlignment - 内容的垂直对齐方式
     *     IsEnabled - 是否可用
     *     IsEnabledChanged - IsEnabled 属性的值发生变化时触发的事件
     *     Template - 控件模板,参见 /Controls/UI/ControlTemplate.xaml
     *     
     *     
     * 本例用于演示 Control 的基础知识
     */
    
    using System;
    using Windows.UI;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Media.Imaging;
    using Windows.UI.Text;
    
    namespace Windows10.Controls.BaseControl.ControlDemo
    {
        public sealed partial class Demo1 : Page
        {
            public Demo1()
            {
                this.InitializeComponent();
    
                this.Loaded += Demo1_Loaded;
            }
    
            private void Demo1_Loaded(object sender, RoutedEventArgs e)
            {
                ImageBrush imageBrush = new ImageBrush();
                imageBrush.ImageSource = new BitmapImage(new Uri("ms-appx:///Assets/hololens.jpg", UriKind.Absolute));
                imageBrush.Stretch = Stretch.Fill;
    
                textBox.Background = imageBrush; // 关于各种类型的 Brush 请参见 /Drawing/Brush.xaml
                textBox.Foreground = new SolidColorBrush(Colors.DarkGreen);
                textBox.BorderBrush = new SolidColorBrush(Colors.Red);
                textBox.BorderThickness = new Thickness(0, 0, 0, 100); // 边框的占用空间是完全是在 Control 内部的
                textBox.Padding = new Thickness(20);
    
                textBox.FontSize = 24;
                textBox.FontFamily = new FontFamily("微软雅黑,宋体");
                textBox.FontStretch = FontStretch.Normal;
                textBox.FontStyle = FontStyle.Normal;
                textBox.FontWeight = FontWeights.Normal;
                textBox.CharacterSpacing = 100;
                textBox.IsTextScaleFactorEnabled = true;
    
                // 对于 TextBox 来说 HorizontalContentAlignment 和 VerticalContentAlignment 都是无效的
                // 但是对于 Button 来说则可以通过 HorizontalContentAlignment 和 VerticalContentAlignment 来指定按钮上文字的对齐方式
                textBox.HorizontalContentAlignment = HorizontalAlignment.Center;// 无效,如果需要设置文字内容的水平对齐方式的话请使用 textBox.TextAlignment
                textBox.VerticalContentAlignment = VerticalAlignment.Center; // 无效
    
                textBox.IsEnabledChanged += TextBox_IsEnabledChanged;
                textBox.IsEnabled = false; // 注:如果要修 IsEnabled = false 的样式请查看名为 Disabled 的 VisualState
                textBox.IsEnabled = true;
            }
    
            private void TextBox_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
            {
                textBox.Text += Environment.NewLine;
                textBox.Text += $"textBox.IsEnabled, OldValue:{e.OldValue}, NewValue:{e.NewValue}"; 
            }
        }
    }


    2、演示 Control 的焦点相关的知识点
    Controls/BaseControl/ControlDemo/Demo2.xaml

    <Page
        x:Class="Windows10.Controls.BaseControl.ControlDemo.Demo2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows10.Controls.BaseControl.ControlDemo"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="Orange">
            <StackPanel Name="stackPanel" Background="Blue" Margin="100">
    
                <!--
                    用于演示 TabIndex 和 IsTabStop
                -->
                <TextBox Name="textBox1" TabIndex="5" Margin="5" />
                <TextBox Name="textBox2" TabIndex="3" Margin="5" />
                <TextBox Name="textBox3" IsTabStop="False" TabIndex="4" Margin="5" />
                <TextBox Name="textBox4" TabIndex="1" Margin="5" />
                <TextBox Name="textBox5" TabIndex="2" Margin="5" />
    
    
                <ComboBox Name="cmbTabNavigation" PlaceholderText="HorizontalAlignment" IsTabStop="False" SelectionChanged="cmbTabNavigation_SelectionChanged" Margin="5">
                    <ComboBoxItem IsSelected="True">Local</ComboBoxItem>
                    <ComboBoxItem>Cycle</ComboBoxItem>
                    <ComboBoxItem>Once</ComboBoxItem>
                </ComboBox>
                <!--
                    用于演示 TabNavigation
                    1、Local - 当 focus 至 itemsControl 时,会逐一 focus 其内部的所有 Control 元素,然后退出 focus
                    2、Cycle - 当 focus 至 itemsControl 时,会逐一 focus 其内部的所有 Control 元素,然后再继续无限循环 focus 其内部的所有 Control 元素
                    3、Once - 当 focus 至 itemsControl 时,只会 focus 其内部的第一个 Control 元素,然后退出 focus
                -->
                <ItemsControl Name="itemsControl" Margin="5" HorizontalAlignment="Left">
                    <ItemsControl.Items>
                        <TextBox  />
                        <TextBox  />
                        <TextBox  />
                    </ItemsControl.Items>
                </ItemsControl>
    
                
                <!--
                    用于演示 UseSystemFocusVisuals
                    1、UseSystemFocusVisuals="False" 获取焦点后,不会有任何效果,如果需要自定义获取焦点后的效果的话请在控件模板中设置
                    2、UseSystemFocusVisuals="True" 获取焦点后,由系统绘制效果(我这里测试的效果是,有一个虚线的边框显示)
                -->
                <Button Content="i am button 1" UseSystemFocusVisuals="False" Margin="5" />
                <Button Content="i am button 2" UseSystemFocusVisuals="True" Margin="5" />
                <Button Content="i am button 3" UseSystemFocusVisuals="False" Margin="5">
                    <Button.Template>
                        <ControlTemplate TargetType="Button">
                            <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="FocusStates">
                                        <VisualState x:Name="Focused">
                                            <VisualState.Setters>
                                                <Setter Target="border.BorderThickness" Value="5" />
                                            </VisualState.Setters>
                                        </VisualState>
                                        <VisualState x:Name="Unfocused" />
                                        <VisualState x:Name="PointerFocused" />
                                    </VisualStateGroup>
                                </VisualStateManager.VisualStateGroups>
                                <Border x:Name="border" BorderBrush="Red" BorderThickness="0">
                                    <ContentPresenter x:Name="ContentPresenter"
                                        BorderBrush="{TemplateBinding BorderBrush}"
                                        BorderThickness="{TemplateBinding BorderThickness}"
                                        Content="{TemplateBinding Content}"
                                        ContentTransitions="{TemplateBinding ContentTransitions}"
                                        ContentTemplate="{TemplateBinding ContentTemplate}"
                                        Padding="{TemplateBinding Padding}"
                                        HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                        VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                        AutomationProperties.AccessibilityView="Raw"/>
                                </Border>
                            </Grid>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
    
                
                <!--
                    IsTemplateFocusTarget - 是否是控件内用于获取焦点的元素(附加属性)
                -->
                <Button Content="i am button 4" Margin="5">
                    <Button.Template>
                        <ControlTemplate TargetType="Button">
                            <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                                <Border x:Name="border" BorderBrush="Red" BorderThickness="0">
                                    <StackPanel>
                                        <ContentPresenter x:Name="ContentPresenter"
                                            BorderBrush="{TemplateBinding BorderBrush}"
                                            BorderThickness="{TemplateBinding BorderThickness}"
                                            Content="{TemplateBinding Content}"
                                            ContentTransitions="{TemplateBinding ContentTransitions}"
                                            ContentTemplate="{TemplateBinding ContentTemplate}"
                                            Padding="{TemplateBinding Padding}"
                                            HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                            VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                            AutomationProperties.AccessibilityView="Raw"/>
                                        <!--
                                            Control.IsTemplateFocusTarget="True" - 代表此 Button 控件用于获取焦点的元素是此 TextBlock
                                        -->
                                        <TextBlock Control.IsTemplateFocusTarget="True" Text="IsTemplateFocusTarget" />
                                    </StackPanel>
                                </Border>
                            </Grid>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
    
            </StackPanel>
        </Grid>
    </Page>

    Controls/BaseControl/ControlDemo/Demo2.xaml.cs

    /*
     * Control - Control(继承自 UIElement, 请参见 /Controls/BaseControl/FrameworkElementDemo/)
     *     FocusState - 当前的焦点状态(FocusState 枚举)
     *         Unfocused - 无焦点
     *         Pointer - 通过指针获取的焦点
     *         Keyboard - 通过键盘获取的焦点
     *         Programmatic - 通过 api 获取的焦点
     *     bool Focus(FocusState value) - 设置焦点状态
     *     TabIndex - Tab 键导航顺序(按 tab 键正序导航;按 shift + tab 键倒序导航),默认值为 int.MaxValue
     *     IsTabStop - 是否包含在 Tab 导航中(即是否可获取到焦点)
     *     TabNavigation - Tab 键导航至 Control 内部时的效果
     *         Local - 当 focus 至 Control 时,会逐一 focus 此 Control 内部的所有 Control 元素,然后退出 focus
     *         Cycle - 当 focus 至 Control 时,会逐一 focus 此 Control 内部的所有 Control 元素,然后再继续无限循环 focus 此 Control 内部的所有 Control 元素
     *         Once - 当 focus 至 Control 时,只会 focus 此 Control 内部的第一个 Control 元素,然后退出 focus
     *     UseSystemFocusVisuals - 是否使用系统的焦点效果
     *         false - 在控件模板中设置焦点效果
     *         true - 使用系统的焦点效果(我这里测试的效果是,获取焦点后会显示一个虚线边框)
     *     IsTemplateFocusTarget - 是否是控件内用于获取焦点的元素(附加属性)
     *     GotFocus - 获取焦点时触发的事件(来自 UIElement)
     *     LostFocus - 丢失焦点时触发的事件(来自 UIElement)
     *     
     *     
     * 本例用于演示 Control 的焦点相关的知识点
     */
    
    using System;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Input;
    
    namespace Windows10.Controls.BaseControl.ControlDemo
    {
        public sealed partial class Demo2 : Page
        {
            public Demo2()
            {
                this.InitializeComponent();
    
                this.Loaded += Demo2_Loaded;
            }
            
            private void Demo2_Loaded(object sender, RoutedEventArgs e)
            {
                textBox1.GotFocus += TextBox1_GotFocus;
                textBox2.GotFocus += TextBox2_GotFocus;
                textBox3.GotFocus += TextBox3_GotFocus;
                textBox4.GotFocus += TextBox4_GotFocus;
                textBox5.GotFocus += TextBox5_GotFocus;
            }
    
            private void TextBox1_GotFocus(object sender, RoutedEventArgs e)
            {
                textBox1.Text += textBox1.FocusState;
            }
    
            private void TextBox2_GotFocus(object sender, RoutedEventArgs e)
            {
                textBox2.Text += textBox2.FocusState;
            }
    
            private void TextBox3_GotFocus(object sender, RoutedEventArgs e)
            {
                textBox3.Text += textBox3.FocusState;
            }
    
            private void TextBox4_GotFocus(object sender, RoutedEventArgs e)
            {
                textBox4.Text += textBox4.FocusState;
            }
    
            // 这里当 textBox5 获取到焦点时,立刻指定 textBox2 获取焦点,则会达到禁止 textBox5 获取焦点的同时手动指定下一个焦点对象
            // 如果只是禁止获取焦点的话可以设置 IsTabStop 为 false
            private void TextBox5_GotFocus(object sender, RoutedEventArgs e)
            {
                textBox5.Text += textBox5.FocusState;
    
                // 设置为 FocusState.Unfocused 时会抛异常
                bool success = textBox2.Focus(FocusState.Programmatic);
            }
    
            private void cmbTabNavigation_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                if (itemsControl != null)
                {
                    itemsControl.TabNavigation = (KeyboardNavigationMode)Enum.Parse(typeof(KeyboardNavigationMode), (e.AddedItems[0] as ComboBoxItem).Content.ToString());
                }
            }
        }
    }



    3、演示如何在运行时获取 ControlTemplate 和 DataTemplate 中的元素
    Controls/BaseControl/ControlDemo/Demo3.xaml

    <Page
        x:Class="Windows10.Controls.BaseControl.ControlDemo.Demo3"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows10.Controls.BaseControl.ControlDemo"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        
        xmlns:common="using:Windows10.Common">
    
        <Page.Resources>
            <!--
                ControlTemplate - 控件模板(是 xaml 语言使用的一种方案,其无法在 c# 中定义)
            -->
            <ControlTemplate x:Key="MyControlTemplate" TargetType="ContentControl">
                <Grid x:Name="grid">
                    <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" 
                                      ContentTransitions="{TemplateBinding ContentTransitions}"
                                      Content="{TemplateBinding Content}" 
                                      HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                      Margin="{TemplateBinding Padding}" 
                                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Grid>
            </ControlTemplate>
    
            <!--
                DataTemplate - 数据模板(是 xaml 语言使用的一种方案,其无法在 c# 中定义)
            -->
            <DataTemplate x:DataType="common:Employee" x:Key="MyDataTemplate">
                <TextBlock x:Name="textBlock" Text="{x:Bind Name}" />
            </DataTemplate>
        </Page.Resources>
    
        <Grid Background="Transparent">
            <StackPanel Margin="10 0 10 10">
    
                <local:MyContentControl x:Name="myContentControl" DataContext="{x:Bind CurrentEmployee}" 
                                        Template="{StaticResource MyControlTemplate}"
                                        ContentTemplate="{StaticResource MyDataTemplate}" />
    
            </StackPanel>
        </Grid>
    </Page>

    Controls/BaseControl/ControlDemo/Demo3.xaml.cs

    /*
     * Control - Control(继承自 UIElement, 请参见 /Controls/BaseControl/FrameworkElementDemo/)
     *     GetTemplateChild() - 查找控件模板中的指定名字的元素
     *     OnApplyTemplate() - 应用控件模板时调用(来自 FrameworkElement)
     *     
     * VisualTreeHelper - 可视化树的实用工具类
     *     
     *     
     * 本例用于演示如何在运行时获取 ControlTemplate 和 DataTemplate 中的元素
     */
    
    using Windows.UI;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;
    using Windows10.Common;
    
    namespace Windows10.Controls.BaseControl.ControlDemo
    {
        public sealed partial class Demo3 : Page
        {
            public Employee CurrentEmployee { get; set; } = new Employee() { Name = "wanglei", Age = 36, IsMale = true };
    
            public Demo3()
            {
                this.InitializeComponent();
    
                myContentControl.Loaded += MyContentControl_Loaded;
            }
    
            private void MyContentControl_Loaded(object sender, RoutedEventArgs e)
            {
                // 通过 VisualTreeHelper 获取可视化树结构(借此可以获取数据模板中的元素)
                TextBlock textBlock = Helper.GetVisualChild<TextBlock>(myContentControl, "textBlock");
                textBlock.FontSize = 48;
            }
        }
    
        
        public class MyContentControl : ContentControl
        {
            // override OnApplyTemplate() - 应用控件模板时调用
            protected override void OnApplyTemplate()
            {
                base.OnApplyTemplate();
    
                // 在 OnApplyTemplate() 中通过 GetTemplateChild() 获取控件模板中的指定名字的元素
                Grid grid = (Grid)GetTemplateChild("grid");
                grid.Background = new SolidColorBrush(Colors.Orange);         
            }
        }
    }



    OK
    [源码下载]

  • 相关阅读:
    替换掉一段 以 $ 开头 $ 结尾 的字符串
    react 中使用 codemirror2(在线代码编辑器)读取 yaml 文件
    第四篇:前端读取文件 | FileReader 对象及其属性
    umi 如何使用 Mock 模拟数据
    loading 动画 系列
    网站页面上标签页小图标的添加方式
    Linux tail命令
    Python实现字符串反转的方法
    Redis 配置远程访问
    消息队列
  • 原文地址:https://www.cnblogs.com/webabcd/p/7902513.html
Copyright © 2020-2023  润新知