[源码下载]

背水一战 Windows 10 (78) - 自定义控件: 基础知识, 依赖属性, 附加属性

作者:webabcd

介绍
背水一战 Windows 10 之 控件(自定义控件)

  • 自定义控件的基础知识,依赖属性和附加属性

示例
演示自定义控件的基础知识,依赖属性和附加属性
1、自定义控件的示例
/MyControls/themes/generic.xaml

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <!--
在 themes/generic.xaml 中定义自定义控件的默认样式
-->
<ResourceDictionary.MergedDictionaries>
<!--
注意:
此处在指定 xaml 路径时,要以“项目名”为根路径(因为这个自定控件的项目是要被别的项目引用的)
这个是对的 ms-appx:///MyControls/themes/MyControl1.xaml
这个是错的 ms-appx:///themes/MyControl1.xaml(编译时不会报错,运行时会报错 Failed to assign to property 'Windows.UI.Xaml.ResourceDictionary.Source' because the type 'Windows.Foundation.String' cannot be assigned to the type 'Windows.Foundation.Uri')
-->
<ResourceDictionary Source="ms-appx:///MyControls/themes/MyControl1.xaml"/>
<ResourceDictionary Source="ms-appx:///MyControls/themes/MyControl3.xaml"/>
</ResourceDictionary.MergedDictionaries> </ResourceDictionary>

/MyControls/themes/MyControl1.xaml

<ResourceDictionary
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:MyControl1">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyControl1">
<!--
绑定基类中定义的依赖属性
-->
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel> <!--
绑定自定义依赖属性
-->
<TextBlock Text="{TemplateBinding Title}" Foreground="White" FontSize="24" /> <!--
绑定自定义附加属性
-->
<TextBlock Text="{TemplateBinding local:MyAttachedProperty.SubTitle}" Foreground="Orange" FontSize="24" /> </StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> </ResourceDictionary>

/MyControls/MyAttachedProperty.cs

/*
* 定义一个附加属性(Attached Property)
*
* 依赖属性:可以用于样式, 模板, 绑定, 动画
* 附加属性:全局可用的依赖属性
*/ using Windows.UI.Xaml; namespace MyControls
{
/// <summary>
/// 定义一个附加属性(Attached Property)
/// </summary>
public sealed 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);
} // 注册一个附加属性(winrc 中不支持 public 类型的 field,如果是 dll 项目则无此限制)
private static readonly DependencyProperty SubTitlePropertyField =
DependencyProperty.RegisterAttached(
"SubTitle", // 附加属性的名称
typeof(string), // 附加属性的数据类型
typeof(MyAttachedProperty), // 附加属性所属的类
new PropertyMetadata("", PropertyMetadataCallback)); // 指定附加属性的默认值,以及值发生改变时所调用的方法 // 用属性的方式封装一下 SubTitlePropertyField
public static DependencyProperty SubTitleProperty
{
get
{
return SubTitlePropertyField;
}
} private static void PropertyMetadataCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
object newValue = args.NewValue; // 发生改变之后的值
object oldValue = args.OldValue; // 发生改变之前的值
}
}
}

/MyControls/MyControl1.cs

/*
* 开发一个自定义控件,并定义一个依赖属性(Dependency Property)
*
* 依赖属性:可以用于样式, 模板, 绑定, 动画
* 附加属性:全局可用的依赖属性
*/ using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml; namespace MyControls
{
/// <summary>
/// 开发一个自定义控件,并定义一个依赖属性(Dependency Property)
/// </summary>
// 注意:
// 在 winrc 中用 c# 写的类必须是 sealed 的(否则编译时会报错 Exporting unsealed types is not supported.Please mark type 'MyControls.MyControl1' as sealed)
// 如果是 dll 项目则无此限制
public sealed class MyControl1 : Control
{
public MyControl1()
{
// 指定默认样式为 typeof(MyControl1),即使用 TargetType 为 MyControl1 的样式,即 <Style xmlns:local="using:MyControls" TargetType="local:MyControl1" />
// 如果不指 DefaultStyleKey 的话,则默认使用基类即 Control 的样式
this.DefaultStyleKey = typeof(MyControl1);
} // 通过 DependencyObject.GetValue() 和 DependencyObject.SetValue() 访问依赖属性,这里由 Title 属性封装一下,以方便对依赖属性的访问
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
} // 注册一个依赖属性
// 注意:
// 在 winrc 中不支持 public 类型的 field(在 dll 项目无此限制),所以这里改为 private 的,之后再用 public 属性的方式封装一下即可
// 如果使用了 public 类型的 field 的话,编译时会报错 Type 'MyControls.MyControl1' contains externally visible field 'Windows.UI.Xaml.DependencyProperty MyControls.MyControl1.TitlePropertyField'. Fields can be exposed only by structures
private static readonly DependencyProperty TitlePropertyField =
DependencyProperty.Register(
"Title", // 依赖属性的名称
typeof(string), // 依赖属性的数据类型
typeof(MyControl1), // 依赖属性所属的类
new PropertyMetadata("", PropertyMetadataCallback)); // 指定依赖属性的默认值,以及值发生改变时所调用的方法 // 用属性的方式封装一下 TitlePropertyField
public static DependencyProperty TitleProperty
{
get
{
return TitlePropertyField;
}
} private static void PropertyMetadataCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
object newValue = args.NewValue; // 发生改变之后的值
object oldValue = args.OldValue; // 发生改变之前的值
}
}
}

2、调用自定义控件的示例
Controls/CustomControl/Demo1.xaml

<Page
x:Class="Windows10.Controls.CustomControl.Demo1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Windows10.Controls.CustomControl"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" xmlns:myControls="using:MyControls"> <Grid Background="Transparent">
<StackPanel Margin="10 0 10 10"> <!--
演示自定义控件的基础知识,依赖属性和附加属性
本例所用到的自定义控件请参看:MyControls/MyControl1.cs
--> <!--
依赖属性和附加属性可以用于绑定
-->
<myControls:MyControl1 x:Name="control1" Background="Blue" BorderBrush="Yellow" BorderThickness="1" Width="200" HorizontalAlignment="Left" Margin="5"
Title="{Binding Value, ElementName=slider}"
myControls:MyAttachedProperty.SubTitle="{Binding Value, ElementName=slider}">
</myControls:MyControl1>
<Slider Name="slider" Width="200" Minimum="0" Maximum="200" IsThumbToolTipEnabled="False" HorizontalAlignment="Left" Margin="5" Foreground="Orange" Background="White" Style="{StaticResource MySliderStyle}" /> <!--
依赖属性和附加属性可以用于 Storyboard 动画
但是无法通过 Storyboard 对自定义附加属性做动画,在文档中找到了这样一句话“However, an existing limitation of the Windows Runtime XAML implementation is that you cannot animate a custom attached property.”
-->
<myControls:MyControl1 x:Name="control2" Background="Blue" BorderBrush="Yellow" BorderThickness="1" Width="200" HorizontalAlignment="Left" Margin="5">
<myControls:MyControl1.Resources>
<BeginStoryboard x:Name="storyboard1">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="control2" Storyboard.TargetProperty="Title" Duration="0:0:10" RepeatBehavior="Forever">
<DiscreteObjectKeyFrame KeyTime="0:0:1" Value="w" />
<DiscreteObjectKeyFrame KeyTime="0:0:2" Value="we" />
<DiscreteObjectKeyFrame KeyTime="0:0:3" Value="web" />
<DiscreteObjectKeyFrame KeyTime="0:0:4" Value="weba" />
<DiscreteObjectKeyFrame KeyTime="0:0:5" Value="webab" />
<DiscreteObjectKeyFrame KeyTime="0:0:6" Value="webabc" />
<DiscreteObjectKeyFrame KeyTime="0:0:7" Value="webabcd" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</myControls:MyControl1.Resources>
</myControls:MyControl1> <!--
在 code-behind 中设置依赖属性和附加属性
-->
<myControls:MyControl1 x:Name="control3" Background="Blue" BorderBrush="Yellow" BorderThickness="1" Width="200" HorizontalAlignment="Left" Margin="5" /> </StackPanel>
</Grid>
</Page>

Controls/CustomControl/Demo1.xaml.cs

/*
* 本例用于演示自定义控件的基础知识,依赖属性和附加属性
*/ using MyControls;
using Windows.UI.Xaml.Controls; namespace Windows10.Controls.CustomControl
{
public sealed partial class Demo1 : Page
{
public Demo1()
{
this.InitializeComponent(); this.Loaded += Demo1_Loaded;
} private void Demo1_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
// 设置依赖属性
control3.Title = "我是依赖属性"; // 设置附加属性
control3.SetValue(MyAttachedProperty.SubTitleProperty, "我是附加属性");
}
}
}

OK
[源码下载]

背水一战 Windows 10 (78) - 自定义控件: 基础知识, 依赖属性, 附加属性的更多相关文章

  1. 背水一战 Windows 10 (79) - 自定义控件: Layout 系统, 控件模板, 事件处理

    [源码下载] 背水一战 Windows 10 (79) - 自定义控件: Layout 系统, 控件模板, 事件处理 作者:webabcd 介绍背水一战 Windows 10 之 控件(自定义控件) ...

  2. 背水一战 Windows 10 (87) - 文件系统: 获取文件的属性, 修改文件的属性, 获取文件的缩略图

    [源码下载] 背水一战 Windows 10 (87) - 文件系统: 获取文件的属性, 修改文件的属性, 获取文件的缩略图 作者:webabcd 介绍背水一战 Windows 10 之 文件系统 获 ...

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

    [源码下载] 背水一战 Windows 10 (76) - 控件(控件基类): Control - 基础知识, 焦点相关, 运行时获取 ControlTemplate 和 DataTemplate 中 ...

  4. 背水一战 Windows 10 (75) - 控件(控件基类): FrameworkElement - 基础知识, 相关事件, HorizontalAlignment, VerticalAlignment

    [源码下载] 背水一战 Windows 10 (75) - 控件(控件基类): FrameworkElement - 基础知识, 相关事件, HorizontalAlignment, Vertical ...

  5. 背水一战 Windows 10 (63) - 控件(WebView): 基础知识, 加载 html, http, https, ms-appx-web:///, embedded resource, ms-appdata:///, ms-local-stream://

    [源码下载] 背水一战 Windows 10 (63) - 控件(WebView): 基础知识, 加载 html, http, https, ms-appx-web:///, embedded res ...

  6. 背水一战 Windows 10 (50) - 控件(集合类): ItemsControl - 基础知识, 数据绑定, ItemsPresenter, GridViewItemPresenter, ListViewItemPresenter

    [源码下载] 背水一战 Windows 10 (50) - 控件(集合类): ItemsControl - 基础知识, 数据绑定, ItemsPresenter, GridViewItemPresen ...

  7. 背水一战 Windows 10 (56) - 控件(集合类): ListViewBase - 基础知识, 拖动项

    [源码下载] 背水一战 Windows 10 (56) - 控件(集合类): ListViewBase - 基础知识, 拖动项 作者:webabcd 介绍背水一战 Windows 10 之 控件(集合 ...

  8. 背水一战 Windows 10 (110) - 通知(Tile): secondary tile 模板之基础, secondary tile 模板之文本

    [源码下载] 背水一战 Windows 10 (110) - 通知(Tile): secondary tile 模板之基础, secondary tile 模板之文本 作者:webabcd 介绍背水一 ...

  9. 背水一战 Windows 10 (108) - 通知(Tile): application tile 基础, secondary tile 基础

    [源码下载] 背水一战 Windows 10 (108) - 通知(Tile): application tile 基础, secondary tile 基础 作者:webabcd 介绍背水一战 Wi ...

随机推荐

  1. spring boot 之 错误:SpelEvaluationException: EL1008E: Property or field 'timestamp' cannot be found on object of type 'java.util.HashMap'

    这个错误我也见过很多次了,今天终于理解了其出现的原因. 错误是这样的: 2017-11-23 18:05:39.504 ERROR 4092 --- [nio-8080-exec-3] o.a.c.c ...

  2. 微信小程序 支付功能 服务器端(TP5.1)实现

    首先下载微信支付SDK ,将整个目录的文件放在 /application/extend/WxPay 目录下 在使用SDK之前我们需要对 WxPay.Config.php 进行配置 <?php n ...

  3. 什么是python的全局解释锁(GIL)

    GIL解决了Python中的什么问题? 为什么选取GIL作为解决方案? 对多线程Python程序的影响 为什么GIL还没有被删除? 为什么在Python 3 中GIL没有被移除? 如何处理Python ...

  4. 关于php利用数组中某个字段进行排序

    工作中用到了一个相关的问题,搜索了百度有好多种方法,但是不同方法对应的函数不同,试了几个发现还是下面这个比较好用: array_multisort($sortarray,SortRank,$sortl ...

  5. spring-security使用

    极客学院Spring Security 例子 <?xml version="1.0" encoding="UTF-8"?> <beans:be ...

  6. linux下启动tomcat服务

     Linux下tomcat服务的启动.关闭与错误跟踪,使用PuTTy远程连接到服务器以后,通常通过以下几种方式启动关闭tomcat服务:切换到tomcat主目录下的bin目录(cd usr/local ...

  7. list中null或者空的区别

    1.list 空 默认值是空,即没有值 null 理解为没有对list集合分配内存空间,实际上压根就不存在. 也可以这样理解: null  未建立对象 空    建立对象未放入值 例如  我有一个空着 ...

  8. 十八、Memento 备忘录设计模式

    原理: 代码清单: Memento public class Memento { int mondey; ArrayList fruits; Memento(int mondey){ this.mon ...

  9. python的int方法实现数据类型转换

    int方法默认以十进制来实现数据类型的转换: 举例: str1=" #给定的内容最好是纯数字,当然也可以是数字再掺杂点别的,最好别掺杂,因为会报错 print(type(str1),str) ...

  10. 20175314 《Java程序设计》第二周学习总结

    20175314 <Java程序设计>第二周学习总结 教材学习内容总结 我在APPstore上发现了一个可以支持我们在IOS系统上学习实践Java程序的开发环境,只需要购买专业版就可以使用 ...