为Silverlight控件的属性值编辑
介绍
这部分是该系列的变化及时执行设计Silverlight的工具包 2009年3月发布 。 这个职位讨论如何加强物业为Silverlight控件使用属性编辑经验值编辑器和类型转换器。 我将首先描述/ Silverlight的设计可扩展框架的总体属性编辑架构在WPF中,然后用例子Silverlight的工具包 2009年3月发布展示它是如何做的,时间开发Silverlight的设计独特的问题/过关英寸
属性编辑架构
视觉编辑对象属性是一个设计师的重要组成部分。 设计师通常不知道如何使自定义类型(结构,类或接口),更不用说提供一个很好的编辑用户界面性能。 控制开发者通常需要提供的TypeConverter , PropertyValueEditor ,或两者兼而有之,提供渲染/编辑用户界面和XAML序列化的自定义类型的属性。
设计者可扩展框架定义了三种类型的属性值编辑器:内置编辑器,扩展编辑器,对话框编辑器,每个类实现:
编辑编辑界面定义那些由DataTemplate中 。 正在编辑的财产暴露在担任编辑的DataContext的PropertyValue类型。 编辑用户界面通常绑定到相关物业正在编辑的性能通过三个一PropertyValue : 价值 , stringValue的 ,或收藏 。
PropertyValueEditor
PropertyValueEditor持有单一内联编辑的定义InlineEditorTemplate财产。 内联编辑器内显示属性窗口。 下面是一个简单的例子InlineEditorTemplate使用一个TextBox来显示和编辑属性:
x:Key ="TextBoxEditor" > <DataTemplate中 谢:关键 =“TextBoxEditor”> Text ="{Binding Path=Value}" /> <TextBox的Text =“(绑定路径=值)”/> > </ DataTemplate中 >
ExtendedPropertyValueEditor
x:Key ="inlineEditor" > <DataTemplate中 谢:关键 =“inlineEditor”> Content ="..." Command ="{x:Static PropertyEditing:PropertyValueEditorCommands.ShowDialogEditor}" /> <“ 按钮 内容 ="..." 指挥 =”(谢:静态PropertyEditing:PropertyValueEditorCommands.ShowDialogEditor)“/> > </ DataTemplate中 > x:Key ="extendedEditor" xmlns:PropertyEditing ="clr-namespace:Microsoft.Windows.Design.PropertyEditing;assembly=Microsoft.Windows.Design.Interaction" > <DataTemplate中 谢:关键=“extendedEditor”xmlns:PropertyEditing =“CLR的命名空间:Microsoft.Windows.Design.PropertyEditing;集会= Microsoft.Windows.Design.Interaction”> x:Name ="slider" Value ="{Binding Path=Value}" /> < 滑块 谢:名称 =“滑杆” 值 =“(绑定路径=值)”/> > </ DataTemplate中 >
DialogPropertyValueEditor
DialogPropertyValueEditor编辑也有两个:内联编辑器继承了PropertyValueEditor ,和一个额外的对话框编辑器的定义DialogEditorTemplate财产。 在弹出对话框编辑器通常是通过了行内编辑器PropertyValueEditorCommands 。 ShowDialogEditor命令。 下面是一个简单的例子:
x:Key ="inlineEditor" > <DataTemplate中 谢:关键 =“inlineEditor”> Content ="..." Command ="{x:Static PropertyEditing:PropertyValueEditorCommands.ShowDialogEditor}" /> <“ 按钮 内容 ="..." 指挥 =”(谢:静态PropertyEditing:PropertyValueEditorCommands.ShowDialogEditor)“/> > </ DataTemplate中 > x:Key ="dialogEditor" xmlns:PropertyEditing ="clr-namespace:Microsoft.Windows.Design.PropertyEditing;assembly=Microsoft.Windows.Design" > <DataTemplate中 谢:关键=“dialogEditor”xmlns:PropertyEditing =“CLR的命名空间:Microsoft.Windows.Design.PropertyEditing;集会= Microsoft.Windows.Design”> > < 网 > > <Grid.ColumnDefinitions> Width ="Auto" /> <ColumnDefinition 宽度 =“自动”/> Width ="*" /> <ColumnDefinition 宽度 =“*”/> > </ Grid.ColumnDefinitions> > <Grid.RowDefinitions> Height ="*" /> <RowDefinition 高度 =“*”/> Height ="*" /> <RowDefinition 高度 =“*”/> > </ Grid.RowDefinitions> Text ="User Name:" VerticalAlignment ="Center" HorizontalAlignment ="Right" Margin ="0,0,4,4" /> <TextBlock的 文本 =“用户名:”VerticalAlignment =“中心”HorizontalAlignment =“右” 保证金 =“0,0,4,4”/> Text ="{Binding Path=Value}" VerticalAlignment ="Center" HorizontalAlignment ="Stretch" Margin ="0,0,4,4" Grid . Column ="1" /> <TextBox的Text =“()绑定路径=价值”VerticalAlignment =“中心”HorizontalAlignment =“弹力” 保证金 =“0,0,4,4” 网格 。 栏 =“1”/> > </ 网格 > > </ DataTemplate中 >
实现自定义属性编辑器
为了实现一个Silverlight控件自定义属性编辑器:
- 实现自定义的属性编辑器类
- 继承PropertyValueEditor,ExtendedPropertyValueEditor,或DialogPropertyValueEditor
- 设置它的编辑模板(补): InlineEditorTemplate , ExtendedEditorTemplate ,和/或DialogEditorTemplate ;
- 联想到一个Silverlight控件属性通过AddCustomAttributes电话,类似的自定义属性编辑器
attributeTableBuilder.AddCustomAttributes( typeof运算 (MyControl) “MyProperty” (MyValueEditor))); 新PropertyValueEditor.CreateEditorAttribute(typeof运算 (MyValueEditor)));
- 一个正确执行财产的价值编辑器必须满足以下要求:
- 属性值编辑器的设计必须使内联编辑和编辑扩展部分可以单独使用。
- 编辑属性值不能存储状态。 编辑属性值是无状态的,可能是由一个主机实现缓存,并且可以重新使用多个属性值。
- 属性值的编辑不要以为只有一个值编辑器部分(查看/内嵌/扩展)控制处于活动状态在一个特定的时间。 例如,一个对话框,可以认为一部分,内嵌的一部分,并扩展用户界面的一部分,同时活跃。
- 一个控制执行财产的价值,作为一个编辑的部分不能存储状态。 作为实施的控制值编辑器的一部分,不应认为它只会被绑定到一个属性值。 控制可循环使用来改变不同的属性值。 任何被缓存的信息应该被刷新,如果数据模型更新。
- 一个控制执行财产的价值,作为一个编辑器的一部分,必须无法对主机或母公司控制的任何假设。 唯一的通信使用的机制应该是PropertyValue数据模型,通过方式的DataContext ,和一套标准的命令。
同时引用WPF和Silverlight大会
一个设计大会是一个.NET之间/ WPF的集会由Visual Studio或混合加载,但它通常需要参考的Silverlight组件(至少在大会提供Silverlight控件设计时功能的)。 这可以创造参考设计组装项目含糊:它有时需要引用相同的完全限定在两个WPF和Silverlight类型,例如在双方的WPF和Silverlight的System.Windows.dll PresentationFramework.dll System.Windows.FrameworkElement。 为了避免混淆Visual Studio中,你可以使用外部别名来区分WPF和Silverlight的参考。
例如,见下面的Controls.DataVisualization.Toolkit.Design项目在Silverlight 3工具包截图2009年3月发布 :
- 该项目引用都PresentationFramework和System.Windows,但System.Windows下Silverlight的别名,而不是默认的全局别名。 Silverlight的别名System.Windows下参考坚持英寸csproj文件如下:
Include ="System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, processorArchitecture=MSIL" > < 参考 包含 =“System.Windows,版本= 2.0.5.0,文化=中立,PublicKeyToken = 7cec85d7bea7798e,processorArchitecture = MSIL”> > False </ SpecificVersion > <SpecificVersion> SpecificVersion>假</ > ..\Binaries\System.Windows.dll </ HintPath > <HintPath> .. \二进制\ System.Windows.dll </ HintPath> > False </ Private > < 私营 >假</ 私人 > > Silverlight </ Aliases > < 别名 >的Silverlight </ 别名 > > </ 参考 “>
- 在源代码中,我们添加
Silverlight的外部别名; 使用 Silverlight的社工=::System.Windows;
和参考Silverlight的FrameworkElement的通过社工::FrameworkElement的。
TextBoxEditor
有内联项目在Controls.DataVisualization.Toolkit.Design编辑TextBoxEditor用于显示和编辑标题对象[区|酒吧|泡泡|专栏|线|馅饼|散]系列和图表控件,如下图所示,类型属性:
文字填写在标题字段属性窗口右侧会自动显示在XAML中,在中间设计的意见。
随后的TextBoxEditor实施前所述的步骤:
- TextBoxEditor是PropertyValueEditor子类。 它规定InlineEditorTemplate在其默认构造函数。 在这里,我用代码而不是XAML来构建DataTemplate中 ,因为某种我无法XAML来构建,和一切在XAML可以是C#重写反正。
- 这是与Chart.Title在ChartMetadata.cs(见实施在Silverlight工具包的设计时代特征的更多信息* Metadata.cs文件)
TextBoxEditor.cs:
/ /(c)版权所有微软公司。 / /此源是受微软公共许可证(女士特等)。 / /请参阅详情http://go.microsoft.com/fwlink/?LinkID=131993的。 / /保留所有其他权利。 使用系统; 使用 Microsoft.Windows.Design.PropertyEditing; 使用 System.Windows; 使用 System.Windows.Data; 命名空间 System.Windows.Controls.DataVisualization.Design ( / / / <summary> / / /简单的TextBox内联编辑。 / / / </摘要> 公共部分类 TextBoxEditor:PropertyValueEditor ( / / / <summary> / / /保存从PropertyValueEditor构造原型。 / / / </摘要> / / / <param name="inlineEditorTemplate">内联编辑的模板。</帕拉姆库马拉> 公共 TextBoxEditor(DataTemplate中inlineEditorTemplate) : 基地 (inlineEditorTemplate) () / / / <summary> / / /默认构造函数生成默认的文本框内嵌编辑模板。 / / / </摘要> 公共 TextBoxEditor() ( (TextBox)); FrameworkElementFactory文本= 新FrameworkElementFactory(typeof运算 (文本框)); 约束力= 新的绑定(); ); binding.Path = 新 PropertyPath(“值”); binding.Mode = BindingMode.TwoWay; textBox.SetBinding(TextBox.TextProperty,装订); DataTemplate中dt的= 新 DataTemplate中(); dt.VisualTree =文本; InlineEditorTemplate = dt的; ) ) )
CultureInfoEditor
我的同事的RJ写TimePicker.Culture物业内联编辑CultureInfoEditor,因为经验共混默认编辑的CultureInfo的XAML中导致无效。 下面的截图显示了CultureInfoEditor使用一个ComboBox来显示所有的CultureInfo并生成正确的XAML。
CultureInfoEditor是一个比TextBoxEditor更复杂的例子,真正显示了如何通过基本属性与DataContext的属性编辑器相关联。
CultureInfoEditor.cs:
/ /(c)版权所有微软公司。 / /此源是受微软公共许可证(女士特等)。 / /请参阅详情http://go.microsoft.com/fwlink/?LinkID=131993的。 / /保留所有其他权利。 使用的System.Reflection; 使用 Microsoft.Windows.Design.PropertyEditing; 使用 System.Globalization; 使用 System.ComponentModel; 命名空间 System.Windows.Controls.Input.Design ( / / / <summary> / / /编辑器的CultureInfo。 / / / </摘要> / / / <remarks>目前不支持绑定到从XAML编辑器。</备注> 公共类 CultureInfoEditor:PropertyValueEditor ( / / / <summary> / / /组合框被用来编辑该值。 / / / </摘要> 私营组合框_owner; / / / <summary> / / /保存从PropertyValueEditor构造原型。 / / / </摘要> / / / <param name="inlineEditorTemplate">内联编辑的模板。</帕拉姆库马拉> 公共 CultureInfoEditor(DataTemplate中inlineEditorTemplate) : 基地 (inlineEditorTemplate) () / / / <summary> / / /默认构造函数生成一个ComboBox内联编辑模板。 / / / </摘要> 公共 CultureInfoEditor() ( / /这里不使用数据绑定,因为Silverlight不支持 / /在WPF CultureConverter是混合使用。 (ComboBox)); FrameworkElementFactory组合框= 新FrameworkElementFactory(typeof运算 (组合框)); comboBox.AddHandler( ComboBox.LoadedEvent, 新 RoutedEventHandler( (发件人,电子)=>“ ( _owner =(组合框)寄件人; _owner.SelectionChanged + = EditorSelectionChanged; 数据= INotifyPropertyChanged的_owner.DataContext 作为 INotifyPropertyChanged的; ) 如果 (数据!= 空 ) ( data.PropertyChanged + = DatacontextPropertyChanged; ) _owner.DataContextChanged + = CultureDatacontextChanged; ))); comboBox.SetValue(ComboBox.IsEditableProperty, 假 ); comboBox.SetValue(ComboBox.DisplayMemberPathProperty,“显示名称”); comboBox.SetValue(ComboBox.ItemsSourceProperty,CultureInfo.GetCultures(CultureTypes.SpecificCultures)); DataTemplate中dt的= 新 DataTemplate中(); dt.VisualTree =组合框; InlineEditorTemplate = dt的; ) / / / <summary> / / /把手SelectionChanged事件的所有者控制的。 / / / </摘要> / / / <param name="sender">事件源。</帕拉姆库马拉> / / / <param name="e">的<see cref="System.Windows.Controls.SelectionChangedEventArgs"/> / / /实例包含事件数据。</帕拉姆库马拉> sender, SelectionChangedEventArgs e) 私人无效 EditorSelectionChanged( 对象发件人,SelectionChangedEventArgs五) ( / /序列化的名称。 对象的DataContext = _owner.DataContext; 的DataContext 。GetType() 。GetProperty(“价值”,BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty) 。setValue方法(DataContext的,((的CultureInfo)_owner.SelectedItem)。名称, 新的对象 []()); ) / / / <summary> / / /把手上下文对象的PropertyChanged事件的。 / / / </摘要> / / / <param name="sender">事件源。</帕拉姆库马拉> / / / <param name="e">的<see cref="System.ComponentModel.PropertyChangedEventArgs"/>实例包含事件数据。</帕拉姆库马拉> sender, PropertyChangedEventArgs e) 私人无效 DatacontextPropertyChanged( 对象发件人,PropertyChangedEventArgs五) ( / /反序列化的名称。 ) 如果 (e.PropertyName ==“价值”) ( 对象的值 =发件人 。GetType() 。GetProperty(“价值”,BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty) 。的getValue(发件人, 新的对象 []()); != null ) 如果 ( 价值 != 空 ) ( ) 如果 ( 值是字符串 ) ( .ToString()); 新的CultureInfo的CultureInfo setCulture =( 价值 。的ToString()); _owner.SelectedItem = setCulture; ) ) ) ) / / / <summary> / / /调用时的上下文改变。 / / / </摘要> / / / <param name="sender">发件人。</帕拉姆库马拉> / / / <param name="e">的<see cref="System.Windows.DependencyPropertyChangedEventArgs"/>实例包含事件数据。</帕拉姆库马拉> sender, DependencyPropertyChangedEventArgs e) 私人无效 CultureDatacontextChanged( 对象发件人,DependencyPropertyChangedEventArgs五) ( INotifyPropertyChanged的老= e.OldValue 作为 INotifyPropertyChanged的; ) 如果 (老!= 空 ) ( old.PropertyChanged -= DatacontextPropertyChanged; ) INotifyPropertyChanged的newDataContext = INotifyPropertyChanged的e.NewValue 作为 ; ) 如果 (newDataContext!= 空 ) ( newDataContext.PropertyChanged + = DatacontextPropertyChanged; ) ) ) )
ExpandableObjectConverter
由于在开始时,除了讨论自定义属性值编辑器,有时你可以使用适当的类型转换器,以提供良好的编辑体验和XAML序列化。 一个例子是ColumnSeries.DependentRangeAxis:它IRangeAxis类型,配方不知道如何编辑它,所以它显示DependentRangeAxis,因为只有在属性面板读取。 通过关联ExpandableObjectConverter到ColumnSeries.DependentRangeAxis:
b.AddCustomAttributes( Extensions.GetMemberName <ColumnSeries>(十=>“x.DependentRangeAxis) (ExpandableObjectConverter))); 新TypeConverterAttribute(typeof运算 (ExpandableObjectConverter))); b.AddCustomAttributes( Extensions.GetMemberName <ColumnSeries>(十=>“x.IndependentAxis) (ExpandableObjectConverter))); 新TypeConverterAttribute(typeof运算 (ExpandableObjectConverter)));
混合显示一个新的按钮,旁边的这个属性面板属性,当点击时,它弹出的对话框中选择对象,与物业的类型IRangeAxis过滤:
结论
配方和Silverlight一起让设计师创造出惊人的用户界面对实际直接控制,因此它是非常重要的控件开发作为整体控制设计和执行工作的一部分设计师的经验。 有一个自定义属性编辑器,编辑提供很好的用户界面,并产生正确的XAML是一个设计者经验的重要组成部分。 希望这个帖子可以帮助您了解如何创建自定义属性编辑器。 谢谢!








最近的评论