xaml中如何初始化数组初始化类型的依赖属性

WPF 依赖属性的创建与使用
WPF 中最大的亮点当属 Binding 了,.NET 给我们提供了足够多的属性来让我们非常方便地进行数据绑定等操作。但即使如此,依然会有想编写自己的属性来进行 Binding 等操作。
在 WPF 中,微软将属性的概念延伸了一下,推出了“依赖属性”这个概念。所谓依赖属性,就是自己本身没有值而值是依赖别人的值。
为什么要使用依赖属性呢?举个例子,一个 TextBlock 有上百个属性,但是基本上我们常用的就是 Text 属性,当你在使用构造函数创建这个 TextBlock 的时候,这个实例的控件就已经被定下来了,随之而来的是大量不必要的空间浪费。而依赖属性,依赖别人的值而设定自己的值,这节省了大量不必要的空间浪费,而且可以方便的进行数据绑定,所以我们才要用依赖属性。
如何创建一个依赖属性呢?代码如下:
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(string), typeof(Test));
首先依赖属性的访问权限可以是 public 或者 private 和 protected,但是如果是 private 或者 protected 的话,要想让外界访问,就需要给这个依赖属性添加一个 public 的属性访问器以暴露这个依赖属性,稍后会介绍如何给该依赖属性绑定一个 CLR 属性,当然你也可以自己写一个 CLR 属性来封装该依赖属性的值,但这样做会影响我们使用 Binding 等功能。
而 static 和 readonly 是必须的,所以即使你创建了一百个依赖对象,也仅占一个空间,当然这可能有点难以理解,静态的和只读的与我们正常使用依赖属性的情况完全不符,不过你可以暂时或略这里,这样写的原因不是本文想要讲的,我会在之后的博客里讲为什么这样写。
然后是 DependencyProperty ,这是依赖属性类,所以后面的 ContentProperty 就是这个对象了。这里有一个命名规则,就是依赖属性的对象名都已
Peoperty 结尾,这样就表明他是一个依赖属性,方便他人阅读和理解。
你会发现我们并不是用构造函数来创建依赖属性的,而是使用了 DependencyProperty 类中的一个静态方法,来创建一个依赖属性。该方法有多个重载,详细请参见 MSDN 文档,这里使用的是最简单的重载,有三个参数:第一个是一个 String 对象,值为给这个依赖属性绑定的 CLR 属性;第二个为 Type 类型,表明这个依赖属性存储的值是什么类型,注意是这个依赖属性存储的值,这个依赖属性的类型永远是 DependencyProperty ;第三个参数也是
Type 类型,表明拥有该依赖属性的类是哪一个,也可以说把这个依赖属性注册到哪个类里,所以用 Register 这个名字就显得合理了。
下面来看一个稍完整的示例:
首先创建一个 WPF 项目,并创建一个类,名为 Test 。MainWindow.xaml 中代码如下:
&Window x:Class="wpfblog.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"&
&Grid.RowDefinitions&
&RowDefinition/&
&RowDefinition/&
&/Grid.RowDefinitions&
&TextBox x:Name="textBox" Grid.Row="0"&&/TextBox&
&Button x:Name="button" Click="button_Click" Grid.Row="1"&点击显示 Content&/Button&
Test.cs 文件中的代码如下:
using System.Collections.G
using System.L
using System.T
using System.Threading.T
using System.W
namespace Blog_DependencyProperty
public class Test : DependencyObject
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(string), typeof(Test));
public Test()
从 Test.cs 的代码中可以看到,创建依赖属性首先要让当前类继承 DependencyObject 类,在这里,一个对象名为 ContentProperty 的依赖属性就创建完成了。
如何为其添加 Binding 呢?MainWindow.xaml.cs 代码如下 :
using System.Collections.G
using System.L
using System.T
using System.Threading.T
using System.W
using System.Windows.C
using System.Windows.D
using System.Windows.D
using System.Windows.I
using System.Windows.M
using System.Windows.Media.I
using System.Windows.N
using System.Windows.S
namespace Blog_DependencyProperty
/// &summary&
/// MainWindow.xaml 的交互逻辑
/// &/summary&
public partial class MainWindow : Window
public MainWindow()
InitializeComponent();
test = new Test();
Binding binding = new Binding("Text") { Source = textBox };
BindingOperations.SetBinding(test, Test.ContentProperty, binding);
private void button_Click(object sender, RoutedEventArgs e)
MessageBox.Show((string)test.GetValue(Test.ContentProperty));
重点在构造函数里,其中第一行代码不必说了,第二行创建了一个 Test 实例,第三行则是添加绑定,数据源是在 XAML 文件中创建的 TextBox 对象,Path 是 Text 属性(这个Text 属性其实是一个 CLR 属性,真正的依赖属性其实是 TextProperty),这里就不再赘述 Path 等概念了;第四行代码是给数据源和数据目标之间添加绑定,如果你使用 test.SetBinding 方法,你会发现微软没有在 DependencyObject 类中提供这个方法,所以你需要使用如第四行所示的代码来建立一个绑定,数据目标是
test 对象,依赖属性是 ContentProperty ,第三个参数就是之前实例化的 binding 了。其实你应该觉得奇怪,数据目标是 test 对象,一般来说应该是以后台代码为数据源,前台 UI 控件为数据目标,这里反了过来,且 test 对象没有 SetBinding 方法,需要使用 BindingOperations 类中的静态方法,这也表达了微软希望 UI 控件作为数据目标,实现数据驱动 UI 的思想(读者也可以从类的层级方面发现问题)。
而后面给按钮添加的事件处理函数很好理解。利用从 DependencyObject 对象继承而来的 GetValue 和 SetValue 方法可以读取或设置依赖属性的值。注意 GetValue 的方法返回值是 object 类型,所以你需要手动转换为你需要的类型。SetValue 方法稍后再讲。
好了,运行一下程序,在 TextBox 中输入内容,点击按钮,就会显示出你输入的内容。
内容就请大家忽略吧,最近博主有点感情受挫。
好了,言归正传,你会发现这里并没有用到创建(或者说注册更合适)依赖属性时的第一个参数,是的,即使没有 CLR 属性,也一样可以完美运行。
那么为什么我们还要有 CLR 属性来封装这个依赖属性的值呢?读者可以试下:
textBox.Text = Test.ContentP
textBox.Text = (string)Test.ContentP
这两行代码都会报错,因为无法将一个 DependencyProperty 类型的对象转换为 string ,当然有无法转为其他一些类型,而我们要想使其作为数据源的 Path 的话(之前是数据目标),就必须要得到它的值,你无法将一个函数用作 Path 吧,所以我们需要一个 CLR 属性。当然,使用 CLR 属性也更符合面向对象设计的一些思想,我们使用也更加方便。
添加如下代码:
public string Content
return (string)GetValue(ContentProperty);
SetValue(ContentProperty, value);
这段代码想必大家都很熟悉了,SetValue 的用法大家也一目了然,这里我们想演示如何使自己创建的依赖属性作为数据源,所以我们将之前的按钮改为一个 TextBlock ,并设置其 x:name 值为 textBlock 。
在 MainWindow.xaml.cs 中,删掉按钮的那个事件处理函数,然后在构造函数中添加如下代码:
textBlock.SetBinding(TextBlock.TextProperty, new Binding("Content") { Source = test });
好了,来让我们运行下吧。什么?等等?还没实现 Inotifypropertychanged 接口?不管怎么样,先让我们运行看看吧。
没错,像这样创建的依赖属性可以直接作为数据源使用。上面这个例子已经证明了现在我们自己创建的这个依赖属性既可以作为数据目标也可以作为数据源。
好了,本篇博客就讲到这里,谢谢大家!欢迎大家批评指正。
Remember !You Make Luck !
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!依赖属性的概念,用途 ,如何新建与使用。本文用做一个自定义TimePicker控件来演示WPF的依赖属性的简单应用。
先上TimePicker的一个效果图。
概念 和 用途:依赖属性是对传统.net 属性的一种封装,使一个传统.net属性支持 WPF 中的 数据绑定、动画、样式 等功能。
新建:任意代码代码文件中 ,输入 propdp 再双击tab键。生成如下的代码块。
&&&& MyProperty: 依赖属性的名称; ownerclass: 当前依赖属性绑定的所有类; new PropertyMetadata 是依赖属性的初始化对象,这里0代表默认值。
public int MyProperty
get { return (int)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
// Using a DependencyProperty as the backing store for MyProperty.
This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(ownerclass), new PropertyMetadata(0));
使用:这里我们使用绑定绑定,稍后使用自定义控件的Time属性来介绍。
如何使用依赖属性构建一个带绑定的TimePicker自定义控件
新建一个项目名称为DependencyPropertyDemo的WPF 项目 ,新建一个TimePicker的自定义控件。Xaml布局如下:
&Grid.ColumnDefinitions&
&ColumnDefinition Width="9*"/&
&ColumnDefinition Width="24"/&
&ColumnDefinition Width="10*"/&
&/Grid.ColumnDefinitions&
&ComboBox Name="cbbHour" Grid.Column="0"/&
&Label Content=":" Grid.Column="1"/&
&ComboBox Name="cbbMinute" Grid.Column="2"/&
BehindCode新建一个名称为Time的依赖属性,如下:
public string Time
get { return (string)GetValue(TimeProperty); }
set { SetValue(TimeProperty, value); }
public static readonly DependencyProperty TimeProperty =
DependencyProperty.Register("Time",
typeof(string),
typeof(TimePicker),
new PropertyMetadata(defaultValue: "00:00",
propertyChangedCallback: null,
coerceValueCallback: coerceValueCallback));
private static object coerceValueCallback(DependencyObject d, object baseValue)
if (baseValue != null)
var control = d as TimeP
var times = baseValue.ToString().Split(':');
control.cbbHour.SelectedItem = times[0];
control.cbbMinute.SelectedItem = times[1];
return baseValue.ToString();
return baseV
这里详细介绍一下PropertyMetadata的三个参数:defaultValue:默认值,不用介绍了;propertyChangedCallback:属性变化后的通知事件,这里不需要任何通知,所以传入null值;coerceValueCallback:这是属性值新值绑定时,通知事件,这里使用得到的值来给控件赋值。到这里Time依赖属性也就完成一半了。
TimePicker属性依赖属性Time的绑定
绑定方式很简单,如下图。若Time是一个普通的.net属性而非依赖属性的话,是不能这样使用绑定方式的。
&local:TimePicker HorizontalAlignment="Left" Margin="137,38,0,0" VerticalAlignment="Top" Width="161"
Time="{Binding StartTime,Mode=TwoWay}"/&
假设添加在TimePicker后台添加一个Code的普通属性,使用绑定的话,会出现如下的状况。
依赖属性使用是有一定限制的,就是他注册的类对象,也就是上文的ownerclass必须继承DependencyObject 这个基类,不过不用担心,WPF大部分元素都间接的集成这个基类。
本文实现的TimePicker控件可以在一些情况下解决WPF下没有Time选择控件的问题。
如果,您认为阅读这篇博客让您有些收获,请点击下面的【推荐】和 【关注】按钮,感谢大家的支持,我是朝兮兮。
阅读(...) 评论()第六章 深入浅出话Binding
& &1、绑定的源可以是任意对象,并通过属性公开自己的数据;
& & & & 绑定的目标必须是依赖对象的依赖属性。
& &2、INotifyPropertyChanged接口,当对象实现了这个接口的时候,当数据源改变的时候可以通知UI同时实现改变,
& & & & 实现原理:当为Binding设置了数据源后,Binding会自动侦听来自这个接口的事件。
& & & &&public event PropertyChangedEventHandler PropertyC
& & & & protected void FirePropertyChanged(string propertyName)
& & & & & & if(PropertyChanged!=null)
& & & & & & & & PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
& & & & 然后在属性的Set访问器重使用
& & & & set
& & & & & & {
& & & & & & & & if (_age != value)
& & & & & & & & {
& & & & & & & & & & _age =
& & & & & & & & & & FirePropertyChanged("Age");
& & & & & & & & }
& & & & & & }
& &3、依赖属性:这类属性的值可以通过Binding依赖在其他对象的属性值上,被其他对象的属性值所驱动。
& &4、绑定路径(Path):需要绑定的值 (PropertyPath类型)
& & & & &bind.Path = new PropertyPath("Name");//设定数据绑定的路径
& & & & &还支持多级路径:Text={Binding Path=Text.Length,ElementName=textBox1,Mode=OneWay}
& &5、绑定模式:OneTime(初始化时的绑定,后面不会再改变)、OneWay(数据源改变UI改变,默认)TwoWay(双向绑定)
& &6、数据源(Source)的来源
& & & & a、普通CLR类型的单个对象:自定义的类或者.NET自带的类型;
& & & & b、集合类型:数组、List&T&、ObservableCollection&T&等
& & & & c、ADO.NET数据对象:DataTable和DataView等(Win8和WP都不支持)
& & & & d、使用XmlDataProvider把XML作为数据的来源(貌似win8不支持)
& & & & e、依赖对象(既可以作为源有可以作为绑定目标)
& & & & &f、 把容器的DataContext指定为源:我们明知道从哪个属性获取数据,但是不知道具体把哪个对象作为Binding源。
& & & & g、ElementName作为数据源:元素之间的绑定
& & & & h、使用Binding类的RelativeSource属性:控件内部绑定(支持本身但是不支持层级相对绑定)
& & & & i、ObjectDataProvider对象指定为Source:当数据源的数据不是通过属性而是通过方法暴露给外界的时候。(貌似Win8不支持)
& & & & k、把使用LINQ检索得到的数据对象作为源。
& &7、转换器IValueConverter
& & &&& Converter:从源到目标的转换
& & & & ConverterBack:从目标到源的转换
& &8、数据校验ValidationgRule 貌似win8和wp不支持,(如果有谁研究过,望回复一起研究下)
第七章 深入浅出话属性
& &1、静态字段在内存中只有一个拷贝,非静态字段则是每一个实例拥有一个拷贝,但无论方法是静态还是非静态,在内存中只会有一份拷贝,区别只是你只能
& & & & 通过类名或者实例名来访问存放指令的内存
& &2、依赖属性:一种可以自己没有值,可以通过Binding从数据源获取得到值,拥有依赖属性的对象称为依赖对象,
& & & &&&节省实例对内存的开销
& & & & &属性值通过Binding依赖在其他对象身上,既可以作为数据源有可以作为数据绑定目标
& &3、依赖属性对内存的使用方式:对象在创建的时候并不包含用于存储数据的空间(即字段所占用的空间)、只保留在需要用到数据的时候能够获得默认值、借用
& & & & &其他对象数据或实时分配空间的能力。
& & & & &a、依赖属性(DependencyProperty)必须以DependencyObject为宿主,通过它的SetValue和GetValue设置和获取值,
& & & & &b、声明必须以&public static readonly开头
& & & & &c、属性成员变量的名字后面要加上Property,以表明他是一个依赖属性
& & & & &d、使用DependencyProperty.Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)创建而不是new,
& & & & & & & &第一个参数用来指明用哪个CLR属性来作为这个依赖属性的包装器(包装器以实例属性暴露依赖属性)。
& & & & & & & &第二个参数用来指明依赖属性存储什么类型的值
& & & & & & & &第三个参数用来指明依赖属性的宿主是什么类型
& & //第一步:继承DependencyObject
& & class StudentDependency:DependencyObject
& & & & //第三步:使用CLR属性作为依赖属性的包装器
& & & & public string Name
& & & & & & get { return (string)GetValue(NameProperty); }
& & & & & & set { SetValue(NameProperty, value); }
& & & & //第二步:注册依赖属性
& & & & public static readonly DependencyProperty NameProperty =
& & & & & & DependencyProperty.Register("Name", typeof(string), typeof(StudentDependency), new PropertyMetadata(null));
& &4、附加属性:一个属性本来不属于某个对象,但是由于某种需求而被后来附加上,即把对象放入一个特定的环境后才具有的属性。
& & & & &作用就是将属性与数据类型(宿主)解耦,让数据类型设计更加灵活
& & & & &本质还是依赖属性,二者仅在包装器和注册上有点区别
& & & &//使用的是两个方法对属性进行赋值
& & & & public static int GetGrade(DependencyObject obj)
& & & & & & return (int)obj.GetValue(GradeProperty);
& & & & public static void SetGrade(DependencyObject obj, int value)
& & & & & & obj.SetValue(GradeProperty, value);
& & & &//使用的时RegisterAttached方法注册
& & & & public static readonly DependencyProperty GradeProperty =
& & & & & & DependencyProperty.RegisterAttached("Grade", typeof(int), typeof(SchoolAttachedProperty), new PropertyMetadata(0));
阅读(...) 评论()Posts - 259,
Articles - 3,
Comments - 1910
分享开发经验,记录开发点滴
13:11 by jv9, ... 阅读,
微软发布Visual Studio 2012 RC和Windows 8 Release Preview版本,从本篇开始,所有实例将基于最新版本开发工具VS2012 RC和Win 8 RP版。 &&下载Visual Studio 2012 RC :&&下载Windows 8 Release Preview:&在上几篇XAML实例教程中,分别介绍XAML对象,属性以及命名空间的概念。从这篇开始,将讨论常见的XAML高级话题,其中包括依赖属性(Dependency Properties), 附加属性(Attached Properties), 事件处理(Event)等。这些话题是Windows 8和Silverlight实际项目中经常用到的开发知识,也是XAML开发语言的精华。 &依赖属性(Dependency Properties) & 依赖属性,英文称为Dependency Properties,是Windows 8,Silverlight特有的属性系统。在传统.Net应用开发中,CLR属性是面向对象编程的基础,主要提供对私有字段的访问封装,开发人员可以使用get和set访问器实现读写属性操作。在Windows 8应用开发中,依赖属性和CLR属性类似,同样提供一个实例级私有字段的访问封装,通过GetValue和SetValue访问器实现属性的读写操作。依赖属性最重要的一个特点是属性值依赖于一个或者多个数据源,提供这些数据源的方式也可以不同,例如,通过数据绑定提供数据源,通过动画,模板资源,样式等方式提供数据源等,在不同的方式数据源下,依赖属性可以实时对属性值进行改变。也正是因为依赖多数据源的缘故,所以称之为依赖属性。 依赖属性可以通过多种不同类型的数据源进行赋值,其赋值顺序的不同影响着属性值的改变。为了能够获取准确的依赖属性值,需要了解不同数据源的优先级别,如下图:&&&1. 从图中可以看到,应用动画占有对以来属性控制的最高优先级,简单理解,无论动画代码定义在当前页面内,还是定义在模板代码内,动画都将获得对页面内依赖属性的最优先控制权。 &2. 次一级优先权是依赖属性本地化操作,分别包括其中包括依赖属性赋值,数据绑定,资源引用等。依赖属性使用方式和CLR属性使用类似,可以使用以下格式对依赖属性进行赋值操作:元素对象.依赖属性 = 属性值&例如: 按钮控件中,宽度属性属于依赖属性(随后实例详解),其赋值方法是: Button.Width = 160; &3. 第三优先权是数据模板和控件模板对依赖属性的控制;4. 其次是样式控制器对依赖属性的控制优先权;5. 最低的依赖属性控制优先权是在定义依赖属性时使用GetValue和SetValue对属性默认的赋值。开发人员可以通过对依赖属性不同优先权的控制,操作页面属性值,使控件或者页面达到需求运行效果。&下面实例帮助大家理解Windows 8依赖属性优先级的应用:该实例仍旧使用前几篇中的XamlGuide项目演示,移植到Visual Studio 2012 RC平台,&&定义一个简单用户控件样式 - ButtonStyle,在样式代码中,定义了按钮的内容文本颜色(Foreground)为“Black”黑色,另外定义字体尺寸(FontSize)为24pt, 同时定义按钮文本内容(Content)是“XAML依赖属性测试”:如果应用以上资源样式到本地按钮控件,运行结果如下:&&&但是,如果在&Grid&中定义一个按钮控件,在该按钮控件中,定义按钮文本内容(Content)为“XAML依赖属性测试”,定义按钮内容文本颜色(Foreground)为“Yellow”黄色,按钮文本字体尺寸(FontSize)为14pt,按钮宽度(Width)为200,同时调用静态资源样式ButtonStyle.&最终运行结果如下:&&根据前文讲述的依赖属性执行优先级,按钮控件本地赋值优先于控件样式,所以以上代码中,忽略了ButtonStyle样式,应用本地依赖属性值生成不同结果。XAML的附加属性(Attached Properties)&Attached Properties,中文称为附加属性,该属性是一种特殊的依赖属性,同时也是XAML中特有的属性之一。其语法调用格式如下:&控件元素对象 附加元素对象.附加属性名 = 属性值 /&&我们可以通过以下几个实例理解附加属性,例如,在布局控件Canvas中定义一个按钮控件,而按钮本身没有任何属性可以控制其在布局控件Canvas中的位置,而在Canvas中,定义了两个依赖属性作为按钮控件的附加属性,帮助按钮控制在Canvas中的位置,其代码如下:&Canvas&&&&&Button&Canvas.Left=&Canvas.Top=&/&&/Canvas&在&Button&控件中,使用了“Canvas.附加属性”,效果如同按钮控件从布局控件中继承了Left和Top两个属性值,这时尽管这两个属性仍旧属于Canvas控件,但是属性值已经附加到了按钮控件上,并产生了效果。另外一个附加属性的实例是TooltipService工具提示服务控件,默认控件生成,不具备动态提示功能,而如果在控件中附加了TooltipService.ToolTip属性,就可以生成动态显示指定提示内容的效果。例如:&Grid&x:Name="LayoutRoot"&Background="{StaticResource&ApplicationPageBackgroundThemeBrush}"&&&&&&&&&&Button&Content="XAML依赖属性测试"&Style="{StaticResource&ButtonStyle}"&&&&&&&&&&&&&&&&Foreground="Yellow"&Width="240"&FontSize="14"&ToolTipService.ToolTip="附加属性效果演示"/&&/Grid&&&和布局控件的Left和Top道理相同,按钮控件中并没有ToolTip属性,只是附加或者可以理解为“继承”了ToolTipService类,生成以上效果。从以上示例可以看出,附加属性主要目的是为了简化代码,增强XAML代码对元素对象的控制。通过对已知类属性的“继承”或者“附加”,在元素对象上实现特有的效果。附加属性的应用还有许多例如动画故事板对目标属性的控制Storyboard.TargetProperty,Grid布局控件的行和列的控制(Row和Column)等。&今天暂时介绍到这里,欢迎留言讨论。&&&&XAML实例教程系列:&&&欢迎大家留言交流,或者加入QQ群交流学习: (一群) 超级群500人&(二群) 超级群500人&(三群) 高级群200人&(四群) 超级群500人&(五群) 高级群200人&(六群) 超级群500人&(八群) 超级群500人&(九群 企业应用开发推荐群) 高级群200人&(十群) 超级群500人&(十一群 企业应用开发推荐群)超级群500人&&&&

我要回帖

更多关于 结构体数组初始化 的文章

 

随机推荐