【问题标题】:WPF's tab items: Specified element is already the logical child of another element. Disconnect it firstWPF 的选项卡项:指定元素已经是另一个元素的逻辑子元素。先断网
【发布时间】:2011-10-09 11:49:40
【问题描述】:

我有一个带有 CloseableTabItems 的 CloseableTabControl 我正在尝试动态添加:

public class CloseableTabControl : TabControl
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new CloseableTabItem();
    }
}  


public class CloseableTabItem : TabItem
{
    public static readonly RoutedEvent CloseTabEvent =
        EventManager.RegisterRoutedEvent("CloseTab", RoutingStrategy.Bubble,
        typeof(RoutedEventHandler), typeof(CloseableTabItem));

    public event RoutedEventHandler CloseTab
    {
        add { AddHandler(CloseTabEvent, value); }
        remove { RemoveHandler(CloseTabEvent, value); }
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        var closeButton = Template.FindName("closeButton", this) as Button;
        if (closeButton != null)
        closeButton.Click += CloseButtonClick;
    }

    void CloseButtonClick(object sender, RoutedEventArgs e)
    {
        RaiseEvent(new RoutedEventArgs(CloseTabEvent, this));
    }
}

XAML 如下:

    <local:CloseableTabControl Grid.Column="2" Grid.Row="1" SelectedIndex="{Binding SelectedTabIndex}" ItemsSource="{Binding TabItems}">
    <local:CloseableTabControl.Resources>
        <DataTemplate DataType="{x:Type TestEditor:TestEditorViewModel}">
             <TestEditor:TestEditorView/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type TestParameterEditor:TestParameterEditorViewModel}">
             <TestParameterEditor:TestParameterEditorView/>
        </DataTemplate>
    </local:CloseableTabControl.Resources>
    <local:CloseableTabControl.ItemContainerStyle>
        <Style TargetType="local:CloseableTabItem">
            <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Grid>
                        <Border Name="Border" Background="{DynamicResource Brush2}" BorderBrush="{DynamicResource Brush5}" BorderThickness="1,1,1,1" CornerRadius="6,6,0,0" >
                            <DockPanel>
                                <ContentPresenter x:Name="ContentSite"
                                     VerticalAlignment="Center"
                                     HorizontalAlignment="Center"
                                     ContentSource="Header"
                                     Margin="12,2,12,2"/>
                                <Button Name="closeButton" 
                                     HorizontalAlignment="Center" 
                                     Margin="3,0,3,0" 
                                     VerticalAlignment="Center" 
                                     Width="16" 
                                     Height="16" 
                                     DockPanel.Dock="Right" 
                                     Style="{DynamicResource CloseableTabItemButtonStyle}" 
                                     ToolTip="Close Tab">
                                     <Path Stretch="Fill" StrokeThickness="0.5" Stroke="#FF333333" Fill="#FF969696" Data="F1 M 2.28484e-007,1.33331L 1.33333,0L 4.00001,2.66669L 6.66667,6.10352e-005L 8,1.33331L 5.33334,4L 8,6.66669L 6.66667,8L 4,5.33331L 1.33333,8L 1.086e-007,6.66669L 2.66667,4L 2.28484e-007,1.33331 Z " HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
                                </Button>
                            </DockPanel>
                         </Border>
                      </Grid>
                      <ControlTemplate.Triggers>
                          <Trigger Property="IsSelected" Value="True">
                              <Setter TargetName="Border" Property="Background" Value="{DynamicResource lightBrush}" />
                          </Trigger>
                          <Trigger Property="IsSelected" Value="False">
                              <Setter TargetName="Border" Property="Background" Value="{DynamicResource Brush1}" />
                          </Trigger>
                      </ControlTemplate.Triggers>
                  </ControlTemplate>
               </Setter.Value>
            </Setter>
            <Setter Property="Header">
                <Setter.Value>
                    <StackPanel Orientation="Horizontal" ToolTip="{Binding Caption}">
                         <Image Height="18" Source="{Binding ImageName}"/>
                         <TextBlock Text="{Binding Title}" Margin="2,0,0,0"/>
                    </StackPanel>
                </Setter.Value>
            </Setter>
         </Style>
      </local:CloseableTabControl.ItemContainerStyle>
  </local:CloseableTabControl>  

当我在这个窗口的视图模型的构造函数中只添加一个选项卡时,一切都很好:

TabItems.Add(TestEditorViewModel);

但是当我添加多个时,我得到了提到的异常。
我尝试按照说明here 并将XAML 分离为ItemTemplateContentTemplate 但这导致StackOverFlowException(这是由模板的ContentPresenter 部分引起的,我不知道为什么) .
有什么想法我应该如何处理这个问题?
谢谢

【问题讨论】:

    标签: wpf wpf-controls tabcontrol


    【解决方案1】:

    问题在于SetterHeader 属性。当第一个TabItem 应用了Style 时,将创建一个新的StackPanel。当创建第二个TabItem 并应用Style 时,StackPanel 将分配给其Header 属性。在 WPF 中,视觉对象只能有 1 个父级,因此您会收到上述异常。相反,您应该定义一个包含StackPanelHeaderTemplate,以便每次将Style 应用于TabItem 时,当WPF 膨胀HeaderTemplate 时会生成一个new StackPanel .

    请参阅此相关帖子:

    WTF WPF TabControl?

    干杯!

    【讨论】:

    • 我想我们几乎同时回复了 :)
    • 我一直认为这个错误类似于给多个人吃相同的饼干。它只是行不通。相反,您需要给他们每个 cookie 配方(模板),以便他们制作自己的 cookie :)
    • 我意识到问题出在某个地方,确实将标题定义删除到模板中,但没有完全理解它。如果您能解释为什么Style 应用了相同 StackPanel(为什么不能将相同的Style 应用到不同的元素),那您将非常友善。
    【解决方案2】:

    问题是

    <Setter Property="Header">
        <Setter.Value>
            <StackPanel Orientation="Horizontal" ToolTip="{Binding Caption}">
                <Image Height="18" Source="{Binding ImageName}"/>
                <TextBlock Text="{Binding Title}" Margin="2,0,0,0"/>
            </StackPanel>
        </Setter.Value>
    </Setter>  
    

    在样式里面。我不确定是什么原因造成的,我认为是由于某种原因将内容设置了两次,但解决方案是使用

     <local:CloseableTabControl.ItemTemplate>
         <DataTemplate>
             <StackPanel Orientation="Horizontal" ToolTip="{Binding Caption}">
                  <Image Height="18" Source="{Binding ImageName}"/>
                  <TextBlock Text="{Binding Title}" Margin="2,0,0,0"/>
             </StackPanel>
         </DataTemplate>
     </local:CloseableTabControl.ItemTemplate>
    

    任何关于究竟是什么问题的解释都将受到欢迎。

    【讨论】:

      猜你喜欢
      • 2012-08-23
      • 2012-02-20
      • 1970-01-01
      • 2023-04-05
      • 2012-11-17
      • 2011-04-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多