views:

641

answers:

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

And this is in other files ...

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

And ...

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

Everything works fine, except the second element.
I get the error:
Cannot set Name attribute value 'SecondElementName' on element 'ElementType'. 'ElementType' is under the scope of element 'ElementType', which already had a name registered when it was defined in another scope.

The custom grids are defined properly. The code will compile and run if I take out the property ---

x:Name="SecondElementName"

--- in Window1.xaml

What is causing this error? How do I get around it? I need to nest one of these custom grids inside the other one, and I need names on both of them so I can bind them to seperate data.

Thanks in advance.

+1  A: 

If you want one within the other, you'd want to put the inner one in the Content property of the first:

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

Also, I'm not sure what you are trying to accomplish here, but I fear it.

Anderson Imes
Sounds like this is the right direction to be heading. Regarding your final sentance: HA! I purposely left out anything that would give away the specifics --- believe me, you don't wanna know. Regarding your solution, I'm getting an error: "The attachable property 'Content' was not found in type 'ElementType'" I've tried "Grid.Content" in its place and I get roughly the same error. Any further ideas?
Giffyguy
I meant "Children", not Content. Looks like you got it, though.
Anderson Imes
+2  A: 

In order to know what to do with nested markup objects, the XAML parser will, among other things, look at whether the .NET class defines a default "content" property to use as a container for such children. This is done with the "ContentPropertyAttribute".

In your case, since I guess you want nested objects to go inside the Grid, and since the children of a grid go in the "Children" property collection, you just need to do the following:

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

If you need to do some logic when adding children to your control (e.g. only allow certain types to be children of your ElementType control), you can instead inherit from IAddChild, and implement the AddChild and AddText methods.

As for the naming problem, it seems that only lookless controls can have named children in an instanced scope. So basically, you can have named children inside ElementType.xaml, but not named children in other markup where you instantiate ElementType. I guess it's because of the way they optimize the logical tree or something. A lookless control, on the other hand, is a control with only code. So if you turn your class into a plain old empty subclass of Grid, it works:

public class ElementType : Grid
{
}

Yay! Less code!

Ludovic
This is interesting as well, but it still doesn't allow me to give the parent and child ElementType objects different names. Does anyone know how I can get them named seperately from each other?
Giffyguy
Oh yeah, sorry... I'll complete my answer above.
Ludovic