2009-07-23 19 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> 

E questo è in altri file ...Come posso annidare elementi XAML personalizzati?

<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> 

E ...

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

tutto funziona bene, tranne il secondo elemento.
Ho ricevuto l'errore:
Impossibile impostare il valore dell'attributo Nome "SecondElementName" sull'elemento "ElementType". 'ElementType' è nell'ambito dell'elemento 'ElementType', che aveva già un nome registrato quando era definito in un altro ambito.

Le griglie personalizzate sono definite correttamente. Il codice verrà compilare ed eseguire se prendo la proprietà ---

x:Name="SecondElementName" 

--- in Window1.xaml

Qual è la causa di questo errore? Come faccio ad aggirarlo? Ho bisogno di nidificare una di queste griglie personalizzate nell'altra, e ho bisogno di nomi su entrambi, in modo da poterli associare a dati separati.

Grazie in anticipo.

risposta

5

Per sapere cosa fare con gli oggetti di markup nidificati, il parser XAML esaminerà, tra le altre cose, se la classe .NET definisce una proprietà di "contenuto" predefinita da utilizzare come contenitore per tali figli. Questo è fatto con "ContentPropertyAttribute".

Nel tuo caso, dal momento che penso che si desidera oggetti nidificati per andare all'interno della griglia, e dal momento che i figli di una griglia vanno nella collezione proprietà "Bambini", è sufficiente effettuare le seguenti operazioni:

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

Se hai bisogno di fare qualche logica quando aggiungi dei bambini al tuo controllo (ad esempio permetti solo che alcuni tipi siano figli del tuo controllo ElementType), puoi invece ereditare da IAddChild e implementare i metodi AddChild e AddText.

Per quanto riguarda il problema di denominazione, sembra che solo i controlli senza look possano avere nomi di bambini in un ambito istanziato. Quindi, in pratica, puoi avere figli con nome dentro ElementType.xaml, ma non nominare figli in altri markup dove istanziate ElementType. Immagino sia per il modo in cui ottimizzano l'albero logico o qualcosa del genere. Un controllo senza look, d'altra parte, è un controllo con solo codice. Quindi, se trasformi la tua classe in una semplice sottoclasse vuota di Grid, funziona:

public class ElementType : Grid 
{ 
} 

Yay! Meno codice!

+0

Anche questo è interessante, ma ancora non mi permette di dare nomi diversi agli oggetti ElementType padre e figlio. Qualcuno sa come posso farli chiamare separatamente gli uni dagli altri? – Giffyguy

+0

Oh sì, scusa ... completerò la mia risposta sopra. – Ludovic

1

Se si desidera uno dentro l'altro, che ci si vuole mettere quella interna della proprietà Content del primo:

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

Inoltre, io non sono sicuro di quello che si sta cercando di realizzare qui , ma temo.

+0

Suona come questa è la direzione giusta per essere voce. Per quanto riguarda la tua sentanza finale: HA! Ho volutamente lasciato fuori tutto ciò che avrebbe dato via i dettagli --- credimi, non vuoi saperlo. Per quanto riguarda la tua soluzione, sto ricevendo un errore: "La proprietà attaccabile 'Contenuto' non è stata trovata nel tipo 'ElementType'" Ho provato "Grid.Content" al suo posto e ottengo all'incirca lo stesso errore. Altre idee? – Giffyguy

+0

Intendevo "Bambini", non Contenuto. Sembra che tu abbia capito, comunque. –

0

Se non si desidera modificare UserControl, utilizzare un comportamento collegato. Quindi ti serve solo lì, dove la XAML-Compile ha fallito! Solo 1 comportamento per ogni UserControl che crea problemi.

in XAML:

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

in 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

Qual è la classe Behavior? Cosa sono io :? –

Problemi correlati