WPF 的选项卡项:指定元素已经是另一个元素的逻辑子元素。先断开连接
我有一个带有 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);
但是当我添加多个选项卡时,我获取提到的异常。
我尝试按照说明操作 此处 并将 XAML 分离为 ItemTemplate
和 ContentTemplate
但这导致了 StackOverFlowException
(这是由ContentPresenter
模板的一部分,我不知道为什么)。
有什么想法我应该如何处理这个问题吗?
谢谢
I have a CloseableTabControl with CloseableTabItems I'm trying to add dynamically:
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));
}
}
and the XAML is as follows:
<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>
Everything is fine when I'm adding only one tab in this window's viewmodel's constructor:
TabItems.Add(TestEditorViewModel);
but when I'm adding more than one I'm getting the mentioned exception.
I've tried to follow the instructions here and separate the XAML to ItemTemplate
and ContentTemplate
but this caused a StackOverFlowException
(that is caused by the ContentPresenter
part of the template, I have no idea why).
Any ideas how should I approach this?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题出在
Header
属性的Setter
上。当第一个TabItem
应用了Style
时,将创建一个新的StackPanel
。当创建第二个TabItem
并应用Style
时,相同StackPanel
将被分配给其标头
属性。在 WPF 中,视觉对象只能有 1 个父级,因此您会收到上面所述的异常。相反,您应该定义一个包含StackPanel
的HeaderTemplate
,以便每次将Style
应用于TabItem
时newStackPanel
是在 WPF 扩充HeaderTemplate
时生成的。请参阅此相关帖子:
WTF WPF TabControl?
干杯!
The problem is with your
Setter
for theHeader
property. When the firstTabItem
has theStyle
applied, a newStackPanel
will be created. When the secondTabItem
is created and has theStyle
applied the sameStackPanel
will be assigned to itsHeader
property. In WPF a visual can only have 1 parent, so you receive the stated exception above. Instead you should define aHeaderTemplate
which contains theStackPanel
so that each time theStyle
is applied for aTabItem
a newStackPanel
is generated when WPF inflates theHeaderTemplate
.Please see this related post:
WTF WPF TabControl?
Cheers!
问题出
在风格内部。我不确定到底是什么原因造成的,我认为是由于某种原因内容被设置了两次,但解决方案是使用
任何关于问题到底是什么的解释将是最受欢迎的。
The problem was
inside the style. I'm not sure what causes it exactly, I think it's the content being set twice for some reason, but the solution is to use
Any explanations as to what exactly is the problem will be most welcome.