公开的ItemCollections导致内容命名时构建失败

时间:2012-03-09 14:42:38

标签: wpf silverlight xaml

我遇到了一个问题,我在其中创建了一个包含两个内容集合的用户控件。为了简单起见,我们会说它有两个控件。

在后面的代码中我暴露了那些itemCollections,以便我可以在另一个控件中声明内容。

例如

<!-- User Control xaml -->
<UserControl>
   <StackPanel Orientation="Horizontal" >
       <ItemsControl x:Name="_itemsControl1" />
       <ItemsControl x:Name="_itemsControl2" />
   </StackPanel>
</UserControl>


//in the codebehind for user control
public partial class TwoControls 
{
    public ItemCollection ItemsOne { get { return _itemsControl1.Items; }}
    public ItemCollection ItemsTwo { get { return _itemsControl2.Items; }}
}


<!-- Using the control in xaml later -->
<Custom:TwoControls>    
    <Custom:TwoControls.ItemsOne>
        <TextBox />
        <TextBox />
        <TextBox />
        <TextBox />
        <TextBox />
    </Custom:TwoControls.ItemsOne>
    <Custom:TwoControls.ItemsTwo>
        <Button />
        <Button />
        <Button />
        <Button />
        <Button />
    </Custom:TwoControls.ItemsTwo>
<Custom:TwoControls>

这实际上适用于一个小问题。一旦我尝试命名任何控件,我就会收到以下错误。

<!-- Using the control in xaml later -->
<Custom:TwoControls>    
    <Custom:TwoControls.ItemsOne>
        <TextBox x:Name="txt"/>

无法在元素'TextBox'上设置名称属性值'txt'。 'TextBox'在元素'TwoControls'的范围内,在另一个范围内定义时已经注册了名称。

如果我实际上不必命名控件,我就不会。我们有一些工具可以运行,期望将某些内容控件命名为构建过程的一部分,我需要它们具有名称。还值得注意的是,我实际上在我的TwoControls类中有几个事件,如果我要将其提取到数据模板,我认为我可以使它工作,但我必须比现在更多地工作。

关于为什么会这样做的任何输入都会很棒。

1 个答案:

答案 0 :(得分:1)

我不想听起来很直率,但每当我遇到这个特殊的名称范围问题时,我都记得我做的事情比WinF方式更多,而不是WPF方式。对于类似于容器的控件,我更多地使用Usercontrols来控制页面控件。

建议可能是创建自定义控件而不是用户控件。

    public class TwoControls: Control
    {
      static TwoControls( )
      {
        DefaultStyleKeyProperty.OverrideMetadata( typeof( TwoControls ) , new FrameworkPropertyMetadata( typeof( TwoControls ) ) );
      }

      public ObservableCollection<UIElement> ItemsOne
      {
        get { return ( ObservableCollection<UIElement> )GetValue( ItemsOneProperty ); }
        set { SetValue( ItemsOneProperty , value ); }
      }
      public static readonly DependencyProperty ItemsOneProperty = DependencyProperty.Register( 
        "ItemsOne" , typeof( ObservableCollection<UIElement> ) , typeof( TwoControls ) , 
        new PropertyMetadata( new ObservableCollection<UIElement>( ) ) );

      public ObservableCollection<UIElement> ItemsTwo
      {
        get { return ( ObservableCollection<UIElement> )GetValue( ItemsTwoProperty ); }
        set { SetValue( ItemsTwoProperty , value ); }
      }
      public static readonly DependencyProperty ItemsTwoProperty = DependencyProperty.Register( 
        "ItemsTwo" , typeof( ObservableCollection<UIElement> ) , typeof( TwoControls ) , 
        new PropertyMetadata( new ObservableCollection<UIElement>( ) ) );
    }
      //The next in your ResourceDictionary
     <Style xmlns:local="clr-namespace:WPFApplication1" TargetType="{x:Type local:TwoControls}">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type local:TwoControls}">
            <StackPanel Orientation="Horizontal">
              <ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ItemsOne}"/>
              <ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ItemsTwo}"/>
            </StackPanel>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

    //The last in your xaml
    <Custom:TwoControls x:Name="twoControls1">
      <Custom:TwoControls.ItemsOne>
        <TextBox x:Name="Test1"/>
        <TextBox x:Name="Test2"/>
        <TextBox x:Name="Test3"/>
        <TextBox x:Name="Test4"/>
        <TextBox x:Name="Test5"/>
      </Custom:TwoControls.ItemsOne>
      <Custom:TwoControls.ItemsTwo>
        <Button x:Name="ButtonTest1"/>
        <Button x:Name="ButtonTest2"/>
        <Button x:Name="ButtonTest3"/>
        <Button x:Name="ButtonTest4"/>
        <Button x:Name="ButtonTest5"/>
      </Custom:TwoControls.ItemsTwo>
    </Custom:TwoControls>