24

What is the difference between:

<Style TargetType="{x:Type Border}">

and:

<Style TargetType="Border">

When and why do I need to use the {x:Type …} ?

4

5 回答 5

15

There is no difference in effect; in both cases the TargetType property will be set to typeof(Border)

The first version {x:Type Border} was needed in the first version of WPF because the compiler did not use the TypeConverter class to convert the string into a Type object and you needed to specify the TypeExtension class to do that for you.

The second version was introduced, if I remember correctly, with Silverlight and quickly found its way to the WPF compiler.

EDIT

My assumption on the TypeConverter class was wrong; this is implemented by the FrameworkElementFactory:

From the documentation:

Type Properties That Support Typename-as-String

WPF supports techniques that enable specifying the value of some properties of type Type without requiring an x:Type markup extension usage. Instead, you can specify the value as a string that names the type. Examples of this are ControlTemplate.TargetType and Style.TargetType. Support for this behavior is not provided through either type converters or markup extensions. Instead, this is a deferral behavior implemented through FrameworkElementFactory.

Silverlight supports a similar convention. In fact, Silverlight does not currently support {x:Type} in its XAML language support, and does not accept {x:Type} usages outside of a few circumstances that are intended to support WPF-Silverlight XAML migration. Therefore, the typename-as-string behavior is built-in to all Silverlight native property evaluation where a Type is the value.

于 2012-06-23T06:59:19.143 回答
6

Although in the given example it makes no difference but actually there is difference between x:Type and TypeName-as-String.

I have recently encountered a situation which shows that x:Type is different from TypeName-as-String when it comes to custom types. From my experience -

x:Type considers the strong name or the version of the assembly (in which type resides) but not TypeName-as-String.

I have explained about my scenario and other details in my blog here -

Importance of specifying AncestorType with x:Type in RelativeSourceBinding

Apart from this, there is also difference in how WPF infers the type. For x:Type TypeExtension is used, whereas for TypeName-as-String FrameworkElementFactory is used (as Erno mentioned).

于 2012-06-23T08:18:35.103 回答
2

Setting this property (TargetType) to Border without assigning the style with an x:Key allows the style to be applied to all Border elements. But when you sets the x:Key to {x:Type Border}, This means that if you give the Style an x:Key value of anything other than {x:Type Border}, the Style would not be applied to all Border elements automatically. Instead, you need to apply the style to the Border elements explicitly.

于 2012-06-23T07:09:54.817 回答
1

Both are exactly same. In either of the cases your style will apply to Border only.

于 2012-06-23T07:00:58.563 回答
0

If you are using XAML 2009, x:Key can be specified as an element, to explicitly support dictionaries keyed by object types other than strings without requiring a markup extension intermediate. See the "XAML 2009" section in this topic. The remainder of the Remarks section applies specifically to the XAML 2006 implementation.

The attribute value of x:Key can be any string defined in the XamlName Grammar or can be an object evaluated through a markup extension. See "WPF Usage Notes" for an example from WPF.

Child elements of a parent element that is an IDictionary implementation must typically include an x:Key attribute that specifies a unique key value within that dictionary. Frameworks might implement aliased key properties to substitute for x:Key on particular types; types that define such properties should be attributed with DictionaryKeyPropertyAttribute.

The code equivalent of specifying x:Key is the key that is used for the underlying IDictionary. For example, an x:Key that is applied in markup for a resource in WPF is equivalent to the value of the key parameter of ResourceDictionary.Add when you add the resource to a WPF ResourceDictionary in code. The x:Type markup extension has a similar function to the typeof() operator in C# or the GetType operator in Microsoft Visual Basic.

The x:Type markup extension supplies a from-string conversion behavior for properties that take the type Type. The input is a XAML type. The relationship between the input XAML type and the output CLR Type is that the output Type is the UnderlyingType of the input XamlType, after looking up the necessary XamlType based on XAML schema context and the IXamlTypeResolver service the context provides.

In .NET Framework XAML Services, the handling for this markup extension is defined by the TypeExtension class.

In specific framework implementations, some properties that take Type as a value can accept the name of the type directly (the string value of the type Name). However, implementing this behavior is a complex scenario. For examples, see the "WPF Usage Notes" section that follows.

Attribute syntax is the most common syntax used with this markup extension. The string token provided after the x:Type identifier string is assigned as the TypeName value of the underlying TypeExtension extension class. Under the default XAML schema context for .NET Framework XAML Services, which is based on CLR types, the value of this attribute is either the Name of the desired type, or contains that Name preceded by a prefix for a non-default XAML namespace mapping.

The x:Type markup extension can be used in object element syntax. In this case, specifying the value of the TypeName property is required to properly initialize the extension.

The x:Type markup extension can also be used as a verbose attribute; however this use is not typical:

于 2012-06-23T09:36:44.830 回答