如何嵌套自定义XAML元素?

时间:2009-07-23 17:35:45

标签: wpf xaml .net-3.5 grid nested

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

这是在其他档案......

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

而且......

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

除了第二个元素外,一切正常 我收到错误:
无法在元素'ElementType'上设置名称属性值'SecondElementName'。 'ElementType'在元素'ElementType'的范围内,在另一个范围内定义时已经注册了名称。

正确定义了自定义网格。如果我取出属性---

,代码将编译并运行
x:Name="SecondElementName"  

---在Window1.xaml

导致此错误的原因是什么?我该如何解决这个问题?我需要将其中一个自定义网格嵌套在另一个中,我需要两个名称,以便将它们绑定到单独的数据。

提前致谢。

3 个答案:

答案 0 :(得分:5)

为了知道如何处理嵌套标记对象,XAML解析器将查看.NET类是否定义了一个默认的“content”属性,以用作此类子对象的容器。这是通过“ContentPropertyAttribute”完成的。

在您的情况下,因为我猜您希望嵌套对象进入网格内部,并且由于网格的子项位于“Children”属性集合中,您只需执行以下操作:

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

如果在向控件添加子项时需要执行某些逻辑(例如,只允许某些类型为ElementType控件的子项),则可以继承IAddChild,并实现AddChild和AddText方法。

至于命名问题,似乎只有无外观控件可以在实例范围内具有命名子项。基本上,您可以在ElementType.xaml中命名子项,但在实例化ElementType的其他标记中不能命名子项。我想这是因为他们优化逻辑树或其他东西的方式。 另一方面,无外观控制是仅具有代码的控件。因此,如果您将您的类转换为Grid的一个普通的旧空子类,它就可以工作:

public class ElementType : Grid
{
}

耶!更少的代码!

答案 1 :(得分:1)

如果你想要一个在另一个中,你想把内在的那个放在第一个的Content属性中:

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

另外,我不确定你在这里要做什么,但我担心。

答案 2 :(得分:0)

如果您不想更改UserControl,请使用附加行为。所以你只需要它,XAML-Compile失败了!每个UserControl只有一个行为会造成麻烦。

在XAML中

 <preview:PreviewControl>
    <i:Interaction.Behaviors>
       <behaviors:UserControlNameBehavior Name="ICanSetNames"/>
    </i:Interaction.Behaviors>
 </preview:PreviewControl>
在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;
        }
    }