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

而且这是在其他文件...如何嵌入自定义XAML元素?

<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'上设置Name属性值'SecondElementName'。 'ElementType'在元素'ElementType'的范围之内,当它在另一个范围中定义时,它已经有了一个名称注册。

自定义网格已正确定义。该代码可以编译和运行,如果我拿出一个物业---

x:Name="SecondElementName" 

---在Window1.xaml

是什么原因造成这个错误?我如何解决它?我需要将这些自定义网格中的一个嵌套到另一个网格中,并且我需要两个名称,以便将它们绑定到单独的数据。

在此先感谢。

回答

5

为了知道如何使用嵌套标记物尽,XAML解析器会,除其他事项外,看看.NET类是否定义了默认的“内容”属性作为这些儿童的容器来使用。这是通过“ContentPropertyAttribute”完成的。

在你的情况,因为我想你想嵌套的对象去网格内,由于网格的孩子的“儿童”的属性集合中去,你只需要做到以下几点:

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

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

至于命名问题,似乎只有无目的的控件可以在实例化范围内命名子项。因此,基本上,您可以在ElementType.xaml内命名子级,但在您实例化ElementType的其他标记中没有命名子级。我想这是因为他们优化逻辑树或其他东西。 另一方面,无目的控制是一个只有代码的控件。所以,如果你把你的班级分成网格的一个普通的老空的子类,它的工作原理:

public class ElementType : Grid 
{ 
} 

耶!代码少!

+0

这也很有趣,但它仍然不允许我为父类和子类ElementType对象提供不同的名称。有谁知道我可以如何让他们单独命名? – Giffyguy 2009-07-23 23:30:12

1

如果你想在另一个内,你会希望把内一个第一的内容属性:

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

另外,我不知道你正试图在这里完成的任务,但我担心它。

+0

听起来像,这是要朝正确的方向。关于你最后的感叹:哈!我故意遗漏了任何可以放弃细节的东西---相信我,你不想知道。关于您的解决方案,我收到一个错误:“在'ElementType'类型中找不到可附加属性'Content'”我尝试过使用“Grid.Content”代替它,并得到大致相同的错误。还有什么想法? – Giffyguy 2009-07-23 21:46:20

+0

我的意思是“孩子”,而不是内容。但是,看起来你知道了。 – 2009-07-24 14:57:15

0

如果您不想更改UserControl,请使用附加的行为。所以你只需要它,那里的XAML编译失败!每个UserControl只有1个行为会造成麻烦。

在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; 
     } 
    }