2009-07-23 11 views
6
<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication1" 
    Title="Window1"> 
    <Grid> 
     <local:ElementType x:Name="FirstElementName"> 
      <local:ElementType x:Name="SecondElementName" Grid.Column="1" Grid.Row="1" /> 
     </local:ElementType> 
    </Grid> 
</Window> 

Y esto es en otros archivos ...¿Cómo puedo anidar elementos XAML personalizados?

<Grid x:Name="InternalElementName" x:Class="WpfApplication1.ElementType" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication1"> 
</Grid> 

Y ...

public partial class ElementType : System.Windows.Controls.Grid { } 

todo funciona bien, excepto el segundo elemento.
Aparece el error:
No se puede establecer el valor del atributo de nombre 'SecondElementName' en el elemento 'ElementType'. 'ElementType' está bajo el alcance del elemento 'ElementType', que ya tenía un nombre registrado cuando se definió en otro ámbito.

Las cuadrículas personalizadas se definen correctamente. El código se compila y ejecuta si tomo a cabo la propiedad ---

x:Name="SecondElementName" 

--- en Window1.xaml

¿Qué está causando este error? ¿Cómo puedo evitarlo? Necesito anidar una de estas cuadrículas personalizadas dentro de la otra, y necesito nombres en ambas para poder vincularlas a datos separados.

Gracias de antemano.

Respuesta

5

Para saber qué hacer con los objetos de marcado anidados, el analizador XAML, entre otras cosas, analizará si la clase .NET define una propiedad de "contenido" predeterminada para usar como contenedor para dichos elementos secundarios. Esto se hace con el "ContentPropertyAttribute".

En su caso, ya que supongo que se desea que los objetos anidados para ir dentro de la cuadrícula, y puesto que los hijos de una rejilla van en la colección de propiedades "niños", sólo tiene que hacer lo siguiente:

[ContentProperty("Children")] 
public partial class ElementType : Grid 
{ 
    // your code here... 
} 

Si necesita hacer un poco de lógica al agregar elementos secundarios a su control (por ejemplo, solo permita que ciertos tipos sean elementos secundarios de su control ElementType), puede heredar de IAddChild e implementar los métodos AddChild y AddText.

En cuanto al problema de nomenclatura, parece que solo los controles sin aspecto pueden haber nombrado a los niños en un ámbito instanciado. Así que, básicamente, puede haber nombrado a los niños dentro de ElementType.xaml, pero no a los niños con nombre en otras marcas donde crea una instancia de ElementType. Supongo que es por la forma en que optimizan el árbol lógico o algo así. Un control sin sentido, por otro lado, es un control con solo código. Así que si usted da vuelta a su clase en una llanura de edad subclase vacío de cuadrícula, funciona:

public class ElementType : Grid 
{ 
} 

Yay! Menos código!

+0

Esto también es interesante, pero todavía no me permite dar nombres diferentes a los objetos ElementType padre e hijo. ¿Alguien sabe cómo puedo conseguir que se nombren por separado el uno del otro? – Giffyguy

+0

Oh, sí, lo siento ... Completaré mi respuesta anterior. – Ludovic

1

Si quieres uno dentro del otro, que le quiere poner la interna en la propiedad contenido de la primera:

<local:ElementType x:Name="FirstElementName"> 
    <local:ElementType.Content> 
     <local:ElementType x:Name="SecondElementName" Grid.Column="1" Grid.Row="1" /> 
    </local:ElementType.Content> 
</local:ElementType> 

Además, no estoy seguro de lo que está tratando de lograr aquí , pero me temo

+0

Suena como esta es la dirección correcta para ser la partida. En cuanto a su último mensaje: ¡HA! A propósito omite cualquier cosa que revele los detalles, créeme, no quieres saber. En cuanto a su solución, aparece un error: "La propiedad acoplable 'Contenido' no se encontró en el tipo 'ElementType'" He intentado con "Grid.Content" en su lugar y recibo aproximadamente el mismo error. ¿Alguna idea adicional? – Giffyguy

+0

Quise decir "Niños", no Contenido. Parece que lo tienes, sin embargo. –

0

Si no desea cambiar el UserControl, utilice un comportamiento adjunto. ¡Así que lo necesitas allí, donde falló la compilación XAML! Solo 1 comportamiento por cada UserControl que causa problemas.

en XAML:

<preview:PreviewControl> 
    <i:Interaction.Behaviors> 
     <behaviors:UserControlNameBehavior Name="ICanSetNames"/> 
    </i:Interaction.Behaviors> 
</preview:PreviewControl> 

en C#:

public class UserControlNameBehavior : Behavior<UserControl> 
    { 
     public string Name { get; set; } 

     protected override void OnAttached() 
     { 
      this.AssociatedObject.Loaded += OnLoaded; 
      base.OnAttached(); 
     } 

     private void OnLoaded(object sender, RoutedEventArgs routedEventArgs) 
     { 
      this.AssociatedObject.Name = this.Name; 
     } 
    } 
+0

¿Qué es la clase de Comportamiento? Que es I:? –

Cuestiones relacionadas