在开发一个WPF应用时,嫌原有的TabItem风格太简单,因此定义了自己的TabItem风格,如下:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}" >
<Border x:Name="layout" BorderBrush="Gray" BorderThickness="2,2,0,0"
Background="{TemplateBinding Background}" Margin="0,5,0,0"
CornerRadius="7,7,0,0" >
<StackPanel Orientation="Horizontal">
<TextBlock Grid.Column="0" Text="{TemplateBinding Header}" Margin="5,5,5,5" />
<Button Grid.Column="1" Content="X" x:Name="btnClose" Height="18" Width="18"
Margin="0,0,5,0" Padding="0"
VerticalAlignment="Center" HorizontalAlignment="Center"
Background="{x:Null}" BorderBrush="{x:Null}"
FontSize="12" FontWeight="Bold" FontFamily="Courier"
Visibility="Hidden"
Command="local:MainWindow.TabClose" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True" >
<Setter Property="Background" Value="LightBlue"/>
<Setter TargetName="layout" Property="Margin" Value="0,2,0,0"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True" SourceName="layout">
<Setter TargetName="btnClose" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
这段style的定义放在了主窗口MainWindow的Resources中。
主窗口中放置了TabControl控件,名称为tabMain。
<Window ...
<Grid>
<TabControl x:Name="tabMain" />
</Grid>
</Window>
后台代码
public partial class MainWindow : Window
{
public static RoutedUICommand TabClose = new RoutedUICommand();
public MainWindow()
{
InitializeComponent();
CommandBindings.Add(new CommandBinding(TabClose, );
}
private void OnAddTab(string title)
{
tabMain.Items.Add(new TabItem()
{
Header = title
});
}
private void OnTabClose(object sender, ExecutedRoutedEventArgs e)
{
if (!(e.Source is TabItem ti))
return;
tabMain.Items.Remove(ti);
}
}
这段代码能够正确执行所有的功能,但在Tab页关闭时,输出窗口出现数据绑定错误
System.Windows.Data Error: 4 : Cannot find source for binding with reference ‘RelativeSource FindAncestor, AncestorType=‘System.Windows.Controls.TabControl’, AncestorLevel=‘1’’. BindingExpression:Path=TabStripPlacement; DataItem=null; target element is ‘TabItem’ (Name=’’); target property is ‘NoTarget’ (type ‘Object’)
这个错误貌似是TabItem在从TabControl中移除时,由于要更新TabStrip而导致。
浏览网上各种帖子,在这篇文章中受到启发
http://www.mindscapehq.com/forums/thread/477486
这篇帖子讨论的是重定义DataGrid 中 Cell 的风格导致了类似的问题,最后的解决方案是将style的定义放入App.xaml文件中,而不是放在MainWindow的Resources里。
经过试验,发现果真如此,将TabItem的style放在App.xaml中,那个绑定错误的消息就消失了。
难道ControlTemplate的定义都需要放在App.xaml中吗?目前只知其然而未知其所以然,暂时Mark一下,待日后有答案了再更新本文。