演练:为 WPF 设计器创建类型转换器
[本文档仅供预览,在以后的发行版中可能会发生更改。包含的空白主题用作占位符。]
本演练演示如何创建自定义类型的类型转换器。 适用于 Visual Studio 的 WPF 设计器 使用类型转换器来回可扩展应用程序标记语言 (xaml) 序列化您的自定义类型。
在本演练中,您将执行下列任务:
创建项目。
创建自定义类型。
创建类型转换器。
创建一个使用自定义类型的控件。
查看自定义类型 属性 窗口。
完成本演练后,您可以为自定义类型创建类型转换器。
备注
您看到的对话框和菜单命令可能会与 " 帮助 " 中的描述不同具体取决于您现用的设置或版本。若要更改设置,请选择在 工具 菜单的 导入和导出设置 。有关更多信息,请参见 Visual Studio 设置。
系统必备
您需要以下组件来完成本演练:
- Visual Studio 2012 RC.
创建项目
第一步是创建应用程序的项目。
创建项目
创建新的 WPF 名为 TypeConverterExample的应用程序项目在 Visual Basic 或 Visual C#。 有关更多信息,请参见 如何:创建新的 WPF 应用程序项目。
在 MainWindow.xaml WPF Designer打开。
创建自定义类型
在此过程中,您创建了 Complex的简单的自定义类型,表示复数。 一个复数有实部和虚部,并且,这些显示为 double 属性。
创建自定义类型
将名为 Complex.vb 或 Complex.cs 的新类添加到 TypeConverterExample 项目。 有关更多信息,请参见 How to: Add New Project Items。
Complex 类的代码文件随即在代码编辑器中打开。
用下面的代码替换 Complex 类定义。
<TypeConverter(GetType(ComplexTypeConverter))> _ Public Class Complex Private realValue As Double Private imaginaryValue As Double Public Sub New() End Sub Public Sub New(ByVal real As Double, ByVal imaginary As Double) Me.realValue = real Me.imaginaryValue = imaginary End Sub Public Property Real() As Double Get Return realValue End Get Set(ByVal value As Double) realValue = value End Set End Property Public Property Imaginary() As Double Get Return imaginaryValue End Get Set(ByVal value As Double) imaginaryValue = value End Set End Property Public Overrides Function ToString() As String Return String.Format( _ CultureInfo.CurrentCulture, _ "{0}{2}{1}", _ Me.realValue, _ Me.imaginaryValue, _ CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator) End Function Public Shared Function Parse(ByVal complexNumber As String) As Complex If String.IsNullOrEmpty(complexNumber) Then Return New Complex() End If 'The parts array holds the real and imaginary parts of the object. Dim separator() As Char = {","} Dim parts() As String = complexNumber.Split(separator) If (parts.Length <> 2) Then Throw New FormatException( _ String.Format( _ "Cannot parse '{0}' into a Complex object because " & _ "it is not in the '<real>, <imaginary>' format.", _ complexNumber)) End If Return New Complex( _ Double.Parse(parts(0).Trim()), _ Double.Parse(parts(1).Trim())) End Function End Class
[TypeConverter( typeof( ComplexTypeConverter ) )] public class Complex { private double realValue; private double imaginaryValue; public Complex() { } public Complex(double real, double imaginary) { this.realValue = real; this.imaginaryValue = imaginary; } public double Real { get { return realValue; } set { realValue = value; } } public double Imaginary { get { return imaginaryValue; } set { imaginaryValue = value; } } public override string ToString() { return String.Format( CultureInfo.CurrentCulture, "{0}{2}{1}", this.realValue, this.imaginaryValue, CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator); } public static Complex Parse(string complexNumber) { if (String.IsNullOrEmpty(complexNumber)) { return new Complex(); } // The parts array holds the real and // imaginary parts of the object. string[] parts = complexNumber.Split(','); if (2 != parts.Length) { throw new FormatException( String.Format( "Cannot parse '{0}' into a Complex object because " + "it is not in the \"<real>, <imaginary>\" format.", complexNumber)); } return new Complex(double.Parse(parts[0].Trim()), double.Parse(parts[1].Trim())); } }
创建类型转换器
现在您已定义了 Complex 类的类型转换器。 ComplexTypeConverter 类转换为其字符串表示形式和返回的一 Complex 对象。 它还提供默认值的列表,在设计器中 属性 窗口中显示。
创建类型转换器
在 Complex 类定义后,插入 ComplexTypeConverter 类的代码。
Public Class ComplexTypeConverter Inherits TypeConverter Private Shared defaultValues As List(Of Complex) = New List(Of Complex)() Shared Sub New() defaultValues.Add(New Complex(0, 0)) defaultValues.Add(New Complex(1, 1)) defaultValues.Add(New Complex(-1, 1)) defaultValues.Add(New Complex(-1, -1)) defaultValues.Add(New Complex(1, -1)) End Sub ' Override CanConvertFrom to return true for String-to-Complex conversions. Public Overrides Function CanConvertFrom( _ ByVal context As ITypeDescriptorContext, _ ByVal sourceType As Type) As Boolean If sourceType Is GetType(String) Then Return True End If Return MyBase.CanConvertFrom(context, sourceType) End Function ' Override CanConvertTo to return true for Complex-to-String conversions. Public Overrides Function CanConvertTo( _ ByVal context As System.ComponentModel.ITypeDescriptorContext, _ ByVal destinationType As System.Type) As Boolean If destinationType Is GetType(String) Then Return True End If Return MyBase.CanConvertTo(context, destinationType) End Function ' Override ConvertFrom to convert from a string to an instance of Complex. Public Overrides Function ConvertFrom( _ ByVal context As ITypeDescriptorContext, _ ByVal culture As System.Globalization.CultureInfo, _ ByVal value As Object) As Object If TypeOf value Is String Then Try Return Complex.Parse(CType(value, String)) Catch ex As Exception Throw New Exception( _ String.Format( _ "Cannot convert '{0}' ({1}) because {2}", _ value, _ value.GetType(), _ ex.Message), ex) End Try End If Return MyBase.ConvertFrom(context, culture, value) End Function ' Override ConvertTo to convert from an instance of Complex to string. Public Overrides Function ConvertTo( _ ByVal context As ITypeDescriptorContext, _ ByVal culture As System.Globalization.CultureInfo, _ ByVal value As Object, _ ByVal destinationType As Type) As Object If destinationType Is Nothing Then Throw New ArgumentNullException("destinationType") End If Dim c As Complex = CType(value, Complex) If (c IsNot Nothing) Then If Me.CanConvertTo(context, destinationType) Then Return c.ToString() End If End If Return MyBase.ConvertTo(context, culture, value, destinationType) End Function Public Overrides Function GetStandardValuesSupported( _ ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean Return True End Function Public Overrides Function GetStandardValues( _ ByVal context As System.ComponentModel.ITypeDescriptorContext) _ As TypeConverter.StandardValuesCollection Dim svc As New StandardValuesCollection(defaultValues) Return svc End Function End Class
public class ComplexTypeConverter : TypeConverter { private static List<Complex> defaultValues = new List<Complex>(); static ComplexTypeConverter() { defaultValues.Add(new Complex(0, 0)); defaultValues.Add(new Complex( 1, 1)); defaultValues.Add(new Complex(-1, 1)); defaultValues.Add(new Complex(-1,-1)); defaultValues.Add(new Complex( 1,-1)); } // Override CanConvertFrom to return true for String-to-Complex conversions. public override bool CanConvertFrom( ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(string)) { return true; } return base.CanConvertFrom(context, sourceType); } // Override CanConvertTo to return true for Complex-to-String conversions. public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { if (destinationType == typeof(string)) { return true; } return base.CanConvertTo(context, destinationType); } // Override ConvertFrom to convert from a string to an instance of Complex. public override object ConvertFrom( ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { string text = value as string; if (text != null) { try { return Complex.Parse(text); } catch (Exception e) { throw new Exception( String.Format("Cannot convert '{0}' ({1}) because {2}", value, value.GetType(), e.Message), e); } } return base.ConvertFrom(context, culture, value); } // Override ConvertTo to convert from an instance of Complex to string. public override object ConvertTo( ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { if (destinationType == null) { throw new ArgumentNullException("destinationType"); } //Convert Complex to a string in a standard format. Complex c = value as Complex; if (c != null && this.CanConvertTo(context, destinationType)) { return c.ToString(); } return base.ConvertTo(context, culture, value, destinationType); } public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { return true; } public override TypeConverter.StandardValuesCollection GetStandardValues( ITypeDescriptorContext context) { StandardValuesCollection svc = new StandardValuesCollection(defaultValues); return svc; } }
在文件的顶部,导入 System.ComponentModel 命名空间,其中包含 TypeConverter 实现。
Imports System.ComponentModel Imports System.Globalization
using System.ComponentModel; using System.Globalization;
创建使用自定义类型的控件
若要查看您的自定义类型及其类型在事件的类型转换器到设计图面,使用类型创建 UserControlComplex属性。
创建一个使用自定义类型的控件
添加一个新的 WPF 用户控件 ComplexNumberControl.xaml 向 TypeConverterExample 项目。 有关更多信息,请参见 如何:向 WPF 项目中添加新项。
查看 ComplexNumberControl的代码。
用下面的代码替换 ComplexNumberControl 类定义。
Partial Public Class ComplexNumberControl Inherits System.Windows.Controls.UserControl Private complexNumberValue As Complex Public Sub New() InitializeComponent() End Sub Public Property ComplexNumber() As Complex Get Return Me.GetValue(ComplexNumberProperty) End Get Set(ByVal value As Complex) Me.SetValue(ComplexNumberProperty, value) End Set End Property Public Shared ReadOnly ComplexNumberProperty As DependencyProperty = DependencyProperty.Register( _ "ComplexNumber", _ GetType(Complex), _ GetType(ComplexNumberControl), _ New PropertyMetadata(New Complex())) End Class
public partial class ComplexNumberControl : UserControl { public ComplexNumberControl() { InitializeComponent(); } public Complex ComplexNumber { get { return (Complex)this.GetValue(ComplexNumberProperty); } set { this.SetValue(ComplexNumberProperty, value); } } public static readonly DependencyProperty ComplexNumberProperty = DependencyProperty.Register( "ComplexNumber", typeof(Complex), typeof(ComplexNumberControl), new PropertyMetadata(new Complex())); }
生成项目。
查看自定义输入 " 属性 " 窗口
,当 ComplexNumberControl 在 WPF 窗口中承载时,您可以查看自定义类型。
若要查看自定义输入 " 属性 " 窗口
打开在 WPF Designer的 MainWindow.xaml。
在 XAML 视图中,用以下代码替换 Window 元素。
<Window x:Class="TypeConverterExample.MainWindow" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:c="clr-namespace:TypeConverterExample" Title="Window1" Height="300" Width="300"> <Grid> <c:ComplexNumberControl ComplexNumber="0,0" /> </Grid> </Window>
在设计视图中单击。 如有必要,请单击顶部的信息栏以重新加载窗口。
在 XAML 视图中,单击 ComplexNumberControl 元素。
在 属性 窗口中,单击 ComplexNumber 属性。
一个下拉箭头。 ComplexNumber 项旁边。
单击下拉箭头可查看默认值的列表。 选择 -1 - 1, 值。
在 XAML 视图中, ComplexNumber 分配更改为 “- 1 ), 1 "。