WPF 以编程方式绑定选定的 TabItem 背景 属性
WPF Bind Selected TabItem Background Property Programmatically
我想以编程方式将 TabItem
的 Background
属性 绑定到自定义 属性。到目前为止,自定义背景仅在未选择 TabItem
时应用:
TabItem
与绑定一起以编程方式生成:
Binding binding = new Binding();
binding.Source = this;
binding.Converter = this;
binding.Path = new PropertyPath("HasChanged");
binding.Mode = BindingMode.OneWay;
binding.TargetNullValue = tabItem.Background;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(tabItem, TabItem.BackgroundProperty, binding);
我实现了接口IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
GradientStopCollection gradient = new GradientStopCollection();
gradient.Add(new GradientStop(Color.FromRgb(255, 234, 199), 0));
gradient.Add(new GradientStop(Color.FromRgb(255, 233, 194), 0.5));
gradient.Add(new GradientStop(Color.FromRgb(255, 225, 173), 0.5));
gradient.Add(new GradientStop(Color.FromRgb(255, 221, 163), 1));
Brush brush = new LinearGradientBrush(gradient, 90);
return (bool)value ? brush : null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
我必须如何绑定 属性 才能影响选定的 TabItem
?
正如 mm8 在问题评论中提供的 link 中所述,您需要覆盖 TabItem 的 ControlTemplate。下面是带有左侧选项卡的 TabControl 和 TabItem 的自定义 ControlTemplate 的实现。通过更改边框的粗细来突出显示所选项目:
<TabControl TabStripPlacement="Left"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Name="tc"
ItemsSource="{Binding MySource, Mode=OneWay}"
ContentTemplate="{StaticResource templateForTheContent}"
ItemTemplate="{StaticResource templateForTheHeader}">
<TabControl.Resources>
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="brdPanel"
CornerRadius="3,0,0,3"
BorderBrush="Black"
Background="{TemplateBinding Background}"
Margin="2,2,0,2"
BorderThickness="1,1,0,1">
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="10,2" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter TargetName="brdPanel"
Property="BorderThickness"
Value="2,2,0,2" />
<Setter TargetName="brdPanel"
Property="Margin"
Value="1,1,0,1" />
</Trigger>
<Trigger Property="IsSelected"
Value="False">
<Setter TargetName="brdPanel"
Property="BorderThickness"
Value="1,1,0,1" />
<Setter TargetName="brdPanel"
Property="Margin"
Value="2,2,0,2" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
</TabControl>
下面的背景绑定被手动设置为 LightCoral(这里的绑定源设置与 OP 的不同,用于演示目的):
MyItemVM myItem=this.tc.Items[0];
TabItem tabItem = (TabItem)this.tc.ItemContainerGenerator.ContainerFromItem(myItem);
Binding binding = new Binding();
binding.Source = myItem;
binding.Path = new PropertyPath("GroupBackground");
binding.Mode = BindingMode.OneWay;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(tabItem, TabItem.BackgroundProperty, binding);
myItem.GroupBackground = Brushes.LightCoral;
MyItemVM myItem=this.tc.Items[1];
tabItem = (TabItem)this.tc.ItemContainerGenerator.ContainerFromItem(myItem);
binding = new Binding();
binding.Source = myItem;
binding.Path = new PropertyPath("GroupBackground");
binding.Mode = BindingMode.OneWay;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(tabItem, TabItem.BackgroundProperty, binding);
myItem.GroupBackground = Brushes.LightCoral;
请注意,这只会更改 TabItem Header 的背景。
我最终使用了 Arie 的 答案的部分内容,但我无法使用他的模板,因为我想要默认的 Windows 标签样式。
我的第一步是删除所有程序生成的绑定和转换器。然后我使用 TabItem
的 Tag
属性 作为布尔值来标记应该突出显示哪些选项卡。
tabItem.Tag = true;
正如 Arie 所说,我需要在我的 XAML 文件中覆盖 TabItem
的模板。我使用 this method 生成了 TabItem
的默认模板。
最后一步是在触发器中定义一些设置器以检查 Tag
属性 是否设置为 true
。此外,您需要定义 Tag
应转换为布尔值而不是字符串。为此,您需要在 Window
元素中定义 sys
:
<Window ...
xmlns:sys="clr-namespace:System;assembly=mscorlib"
... >
将 属性 Tag
解释为布尔值:
<Trigger.Value>
<sys:Boolean>True</sys:Boolean>
</Trigger.Value>
结果 TabItem
模板:
<TabControl ... >
<TabControl.Resources>
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid SnapsToDevicePixels="True">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}">
<ContentPresenter x:Name="Content" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFEAF6FD" Offset="0.15"/>
<GradientStop Color="#FFD9F0FC" Offset="0.5"/>
<GradientStop Color="#FFBEE6FD" Offset="0.5"/>
<GradientStop Color="#FFA7D9F5" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="Tag">
<Trigger.Value>
<sys:Boolean>True</sys:Boolean>
</Trigger.Value>
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFFFEAC7" Offset="0.15"/>
<GradientStop Color="#FFFFE9C2" Offset="0.5"/>
<GradientStop Color="#FFFFE1AD" Offset="0.5"/>
<GradientStop Color="#FFFFDDA3" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="1"/>
<Setter Property="Background" TargetName="Bd" Value="#FFF9F9F9"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="Tag">
<Condition.Value>
<sys:Boolean>True</sys:Boolean>
</Condition.Value>
</Condition>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="#FFFFE5C1"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="False"/>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="Bd" Value="#FF3C7FB1"/>
</MultiTrigger>
<Trigger Property="TabStripPlacement" Value="Bottom">
<Setter Property="BorderThickness" TargetName="Bd" Value="1,0,1,1"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Left">
<Setter Property="BorderThickness" TargetName="Bd" Value="1,1,0,1"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Right">
<Setter Property="BorderThickness" TargetName="Bd" Value="0,1,1,1"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="TabStripPlacement" Value="Top"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-2,-2,-2,-1"/>
<Setter Property="Margin" TargetName="Content" Value="0,0,0,1"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="TabStripPlacement" Value="Bottom"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-2,-1,-2,-2"/>
<Setter Property="Margin" TargetName="Content" Value="0,1,0,0"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="TabStripPlacement" Value="Left"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-2,-2,-1,-2"/>
<Setter Property="Margin" TargetName="Content" Value="0,0,1,0"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="TabStripPlacement" Value="Right"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-1,-2,-2,-2"/>
<Setter Property="Margin" TargetName="Content" Value="1,0,0,0"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="Bd" Value="#FFF4F4F4"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="#FFC9C7BA"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabItem></TabItem>
</TabControl>
我想以编程方式将 TabItem
的 Background
属性 绑定到自定义 属性。到目前为止,自定义背景仅在未选择 TabItem
时应用:
TabItem
与绑定一起以编程方式生成:
Binding binding = new Binding();
binding.Source = this;
binding.Converter = this;
binding.Path = new PropertyPath("HasChanged");
binding.Mode = BindingMode.OneWay;
binding.TargetNullValue = tabItem.Background;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(tabItem, TabItem.BackgroundProperty, binding);
我实现了接口IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
GradientStopCollection gradient = new GradientStopCollection();
gradient.Add(new GradientStop(Color.FromRgb(255, 234, 199), 0));
gradient.Add(new GradientStop(Color.FromRgb(255, 233, 194), 0.5));
gradient.Add(new GradientStop(Color.FromRgb(255, 225, 173), 0.5));
gradient.Add(new GradientStop(Color.FromRgb(255, 221, 163), 1));
Brush brush = new LinearGradientBrush(gradient, 90);
return (bool)value ? brush : null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
我必须如何绑定 属性 才能影响选定的 TabItem
?
正如 mm8 在问题评论中提供的 link 中所述,您需要覆盖 TabItem 的 ControlTemplate。下面是带有左侧选项卡的 TabControl 和 TabItem 的自定义 ControlTemplate 的实现。通过更改边框的粗细来突出显示所选项目:
<TabControl TabStripPlacement="Left"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Name="tc"
ItemsSource="{Binding MySource, Mode=OneWay}"
ContentTemplate="{StaticResource templateForTheContent}"
ItemTemplate="{StaticResource templateForTheHeader}">
<TabControl.Resources>
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="brdPanel"
CornerRadius="3,0,0,3"
BorderBrush="Black"
Background="{TemplateBinding Background}"
Margin="2,2,0,2"
BorderThickness="1,1,0,1">
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="10,2" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter TargetName="brdPanel"
Property="BorderThickness"
Value="2,2,0,2" />
<Setter TargetName="brdPanel"
Property="Margin"
Value="1,1,0,1" />
</Trigger>
<Trigger Property="IsSelected"
Value="False">
<Setter TargetName="brdPanel"
Property="BorderThickness"
Value="1,1,0,1" />
<Setter TargetName="brdPanel"
Property="Margin"
Value="2,2,0,2" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
</TabControl>
下面的背景绑定被手动设置为 LightCoral(这里的绑定源设置与 OP 的不同,用于演示目的):
MyItemVM myItem=this.tc.Items[0];
TabItem tabItem = (TabItem)this.tc.ItemContainerGenerator.ContainerFromItem(myItem);
Binding binding = new Binding();
binding.Source = myItem;
binding.Path = new PropertyPath("GroupBackground");
binding.Mode = BindingMode.OneWay;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(tabItem, TabItem.BackgroundProperty, binding);
myItem.GroupBackground = Brushes.LightCoral;
MyItemVM myItem=this.tc.Items[1];
tabItem = (TabItem)this.tc.ItemContainerGenerator.ContainerFromItem(myItem);
binding = new Binding();
binding.Source = myItem;
binding.Path = new PropertyPath("GroupBackground");
binding.Mode = BindingMode.OneWay;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(tabItem, TabItem.BackgroundProperty, binding);
myItem.GroupBackground = Brushes.LightCoral;
请注意,这只会更改 TabItem Header 的背景。
我最终使用了 Arie 的 答案的部分内容,但我无法使用他的模板,因为我想要默认的 Windows 标签样式。
我的第一步是删除所有程序生成的绑定和转换器。然后我使用 TabItem
的 Tag
属性 作为布尔值来标记应该突出显示哪些选项卡。
tabItem.Tag = true;
正如 Arie 所说,我需要在我的 XAML 文件中覆盖 TabItem
的模板。我使用 this method 生成了 TabItem
的默认模板。
最后一步是在触发器中定义一些设置器以检查 Tag
属性 是否设置为 true
。此外,您需要定义 Tag
应转换为布尔值而不是字符串。为此,您需要在 Window
元素中定义 sys
:
<Window ...
xmlns:sys="clr-namespace:System;assembly=mscorlib"
... >
将 属性 Tag
解释为布尔值:
<Trigger.Value>
<sys:Boolean>True</sys:Boolean>
</Trigger.Value>
结果 TabItem
模板:
<TabControl ... >
<TabControl.Resources>
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid SnapsToDevicePixels="True">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}">
<ContentPresenter x:Name="Content" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFEAF6FD" Offset="0.15"/>
<GradientStop Color="#FFD9F0FC" Offset="0.5"/>
<GradientStop Color="#FFBEE6FD" Offset="0.5"/>
<GradientStop Color="#FFA7D9F5" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="Tag">
<Trigger.Value>
<sys:Boolean>True</sys:Boolean>
</Trigger.Value>
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFFFEAC7" Offset="0.15"/>
<GradientStop Color="#FFFFE9C2" Offset="0.5"/>
<GradientStop Color="#FFFFE1AD" Offset="0.5"/>
<GradientStop Color="#FFFFDDA3" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="1"/>
<Setter Property="Background" TargetName="Bd" Value="#FFF9F9F9"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="Tag">
<Condition.Value>
<sys:Boolean>True</sys:Boolean>
</Condition.Value>
</Condition>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="#FFFFE5C1"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="False"/>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="Bd" Value="#FF3C7FB1"/>
</MultiTrigger>
<Trigger Property="TabStripPlacement" Value="Bottom">
<Setter Property="BorderThickness" TargetName="Bd" Value="1,0,1,1"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Left">
<Setter Property="BorderThickness" TargetName="Bd" Value="1,1,0,1"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Right">
<Setter Property="BorderThickness" TargetName="Bd" Value="0,1,1,1"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="TabStripPlacement" Value="Top"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-2,-2,-2,-1"/>
<Setter Property="Margin" TargetName="Content" Value="0,0,0,1"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="TabStripPlacement" Value="Bottom"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-2,-1,-2,-2"/>
<Setter Property="Margin" TargetName="Content" Value="0,1,0,0"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="TabStripPlacement" Value="Left"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-2,-2,-1,-2"/>
<Setter Property="Margin" TargetName="Content" Value="0,0,1,0"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="TabStripPlacement" Value="Right"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-1,-2,-2,-2"/>
<Setter Property="Margin" TargetName="Content" Value="1,0,0,0"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="Bd" Value="#FFF4F4F4"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="#FFC9C7BA"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabItem></TabItem>
</TabControl>