2012-03-03 14 views
6

considere el siguiente archivo XAML:Por qué es X: No se requiere clave de ControlTemplate en el ResourceDictionary

<Window x:Class="ExpressionVisualizer.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:sle="clr-namespace:System.Linq.Expressions;assembly=System.Core" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <DataTemplate DataType="{x:Type sle:BinaryExpression}"/> 
     <ControlTemplate TargetType="{x:Type ContentControl}"/> 
    </Window.Resources> 
</Window> 

Esto está dando el siguiente error de compilación:

All objects added to an IDictionary must have a Key attribute or some other type of key associated with them. Line 10 Position 10.

Si añado un atributo x:key a la ControlTemplate, compila. Sin embargo, no debería tener que hacer eso. ControlTemplate está decorado con el atributo DictionaryKeyProperty que especifica TargetType como la propiedad clave. Así que mientras especifique un TargetType para mi ControlTemplate, debería no tener que especificar una clave explícita (similar a cómo no tengo que especificar uno en el DataTemplate que he definido).

Tengo una segunda pregunta relacionada de manera tangencial. Si defino una plantilla de control de esta manera (ya sea especificando una clave o no) en XAML, ¿se aplica automáticamente a todos los controles de tipo ContentControl que no especifican otra plantilla o tendré que incrustar la plantilla de control dentro de un estilo? para que eso ocurra?

Respuesta

4

De MSDN ControlTemplate:

If you have a standalone ControlTemplate in the resources section with the TargetType property set to a type, the ControlTemplate does not get applied to that type automatically. Instead, you need to specify an x:Key and apply the template explicitly.

Also note that the TargetType property is required on a ControlTemplate if the template
definition contains a ContentPresenter.

Así que la ControlTemplate no se aplica automáticamente y usted tiene que especificar siempre el x:Key. Por lo tanto, el DictionaryKeyProperty no se aplica.

he hecho un poco de investigación:

Aunque los DictionaryKeyPropertyAttribute MSDN página establece:

WPF Usage Notes

The following list references examples of WPF APIs where this attribute is applied:

ControlTemplate.TargetType 

DataTemplate.DataTemplateKey 

Style.TargetType 

Pero en la página Resources Overview que sólo mencionan Styles, DataTemplates, and Implicit Keys que tiene teclas implícitas. Esto también implica que siempre debe especificar el x:Key para ControlTemplate a pesar del DictionaryKeyProperty.

Por cierto, parece que hay algo mal con el DictionaryKeyPropertyAttirubte ver esto connect issue.

+0

Eso responde la segunda parte de mi pregunta. Sé que necesito especificar una clave x: si quiero hacer referencia a la plantilla en otro lugar del documento, pero omitirla no debería causar un error de compilación. – luksan

+0

He actualizado mi respuesta. Comprueba 'DictionaryKeyProperty' no está haciendo lo que debería ser ... – nemesv

+0

El problema con DictionaryKeyProperty parece no afectar a todos los tipos, ya que el atributo funciona como se especifica en DataTemplate. El problema de Connect es de 2009. Supongo que solo escribiré esto como algo más en WPF que simplemente no funciona y nunca fue probado exhaustivamente. Cada vez que intento desarrollar algo en WPF me tropiezo con este tipo de problemas. Esto nunca ocurre con Windows Forms, todo funciona. Realmente pensé (quizás desearía) que harían que WPF sea más predecible/utilizable en la versión 4.0. – luksan

1

no sé la respuesta a la primera pregunta, sino de la segunda:

I have a second and tangentially related question. If I define a ControlTemplate in this way (either specifying a key or not) in the XAML, does it get automatically applied to all controls of type ContentControl that don't specify another template, or would I have to embed the ControlTemplate inside a Style for that to occur?

No, no se aplicará automáticamente. Los estilos se aplican automáticamente si su clave coincide con el DefaultStyleKey del control; las plantillas de datos son recogidas automáticamente por ContentControl si el tipo de Content coincide con el DataType de la plantilla. Pero no es el caso para las plantillas de control; de todos modos, las plantillas de control generalmente se definen como parte del estilo de un control, rara vez se aplican directamente a un control.

+0

+1 y gracias, no sabía sobre DefaultStyleKey. – luksan

0
<Window x:Class="ExpressionVisualizer.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:sle="clr-namespace:System.Linq.Expressions;assembly=System.Core" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <DataTemplate x:Key="DT" DataType="{x:Type sle:BinaryExpression}"/> 
    <ControlTemplate x:Key="CT" TargetType="{x:Type ContentControl}"/> 
</Window.Resources> 

clave se utiliza para aplicar plantillas en el control como que el botón, cuadro de texto, bloque de texto, etc. Si no lo utiliza entonces templating no está funcionando.

0

Si desea que la plantilla de control se aplica a todo tipo especificado se puede definir un estilo y establecer la propiedad de la plantilla y que estilo con TargetType a su control especificado:

<Window x:Class="ExpressionVisualizer.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:sle="clr-namespace:System.Linq.Expressions;assembly=System.Core" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <DataTemplate x:Key="DT" DataType="{x:Type sle:BinaryExpression}"/> 
    <ControlTemplate x:Key="CT" TargetType="{x:Type ContentControl}"/> 
    <Style TargetType="ContentControl"> 
     <Setter Property="Template" Value="{StaticResource CT}"></Setter> 
    </Style> 
</Window.Resources> 

He probado esto con una botón tipo de destino, pero creo que debería funcionar de esa manera.

Cuestiones relacionadas