首页 文章

WPF TabControl,用C#代码更改TabItem的背景颜色

提问于
浏览
6

嗨,我认为这是初学者的问题 . 我搜索了所有相关问题 . 但是所有这些都是由.xaml回答的 . 但是,我需要的是后面的代码 . 我有一个TabControl . 我需要设置其项目的背景颜色 . 选择,取消选择和悬停时,我需要为项目设置不同的颜色 . 非常感谢你的帮助 . 我想在这里发布我的代码 . 但是,目前,我所拥有的只是TabControl的一个实例和一个名为ActiveTabIndex的属性 .

---------------------------------------编辑1 --------- --------------------------------------

我添加了一个事件SelectionChanged

(this.myTabControl as System.Windows.Controls.TabControl).SelectionChanged = TabSet_SelectionChanged;

void TabSet_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            foreach (System.Windows.Controls.TabItem item in (this.myTabControl as System.Windows.Controls.TabControl).Items)
            {
                if (item == (this.myTabControl as System.Windows.Controls.TabControl).SelectedItem)
                {
                    item.Background = System.Windows.Media.Brushes.Red;
                }
                else
                    item.Background = System.Windows.Media.Brushes.Green;
            }
        }

但是,我实际上只能设置绿色 . 所选项目的背景颜色保留为默认颜色而不是红色 . 关于这个的任何提示?另外,我想知道如何为悬停添加事件 . 没有找到确切的事件 . 再次感谢 .

-----------------------编辑2 ------------------------- -----

经过长时间的长时间讨论 . 我决定(实际上不是我的决定)使用XAML . 是啊 . 我是WPF的新手 . 所以我对此仍有疑问(对此我很抱歉,请耐心等待) . 问题在这里:当鼠标悬停在TabItem上时,我想将背景颜色更改为橙色 . 现在,当鼠标位于ContentPanel和TabItem上时,颜色为橙色 . 当鼠标只在TabItem上时我需要它是橙色的 . (我不确定我是否足够清楚 . )另一个问题是我会让用户设置颜色而不是直接设置为红色 . 我想我需要一些绑定 . 对于这个问题,我稍后会谷歌肯定 . 只想清楚 . 非常感谢你们所有人 . 真有帮助 .

<TabItem x:Class="MyControls.Tab"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <TabItem.Style>
        <Style TargetType="{x:Type TabItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabItem}">
                        <Grid>
                            <Border  Name="Border" Margin="0,0,-4,0" BorderThickness="1,1,1,1" CornerRadius="2,12,0,0" >
                                <ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True"/>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>

                            <Trigger Property="IsSelected" Value="True">
                                <Setter Property="Panel.ZIndex" Value="100" />
                                <Setter TargetName="Border" Property="Background" Value="Red" />
                                <Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" />
                            </Trigger>

                            <Trigger Property="IsSelected" Value="False">
                                <Setter TargetName="Border" Property="Background" Value="Green" />                                
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="Border" Property="Background" Value="Orange" />
                            </Trigger>

                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </TabItem.Style>
</TabItem>

-------------编辑3 ----------------

我觉得我不够清楚 . 这就是现在的情况:如果鼠标位于其他标签上,它工作正常:
enter image description here

但是当鼠标悬停在带圆圈的区域上时,所选项目的背景颜色应为红色而不是橙色:
enter image description here

---------------编辑4 -------------------

感谢大家的回复 . 现在经过与我的用户和其他人的长时间讨论后,我们想要动态更改背景颜色 . 用户想要自己设置颜色 . 基本上,我需要先做一些绑定(如果这是术语) . 我尝试了以下内容 . 但是,所选选项卡不具有红色背景 . 我使用Snoop检查,事实证明背景在本地设置为红色 . 我在这里有点困惑 . 我问了一下,有人给了我使用TemplateBinding的建议,因为它在ControlTemplate下 . 但是,我试图创建依赖属性等等 . 但只是我不明白为什么我应该使用TemplateBinding,因为我读了一些文章说它是编译时绑定 . 我完全糊涂了 . 我是WPF的新手,如果问题是低级问题,我很抱歉 . 再次感谢!

<TabItem x:Class="MyControl.Tab"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <TabItem.Style>
        <Style TargetType="{x:Type TabItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabItem}">
                        <Grid>
                            <Border  Name="Border" Margin="0,0,-4,0" BorderThickness="1,1,1,1" CornerRadius="2,12,0,0" >
                                <ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True"/>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="True">
                                <Setter Property="Panel.ZIndex" Value="100" />
                                <Setter TargetName="Border" Property="Background" Value="{Binding SelectedBgClr}" />
                                <Setter Property="Foreground" Value="Yellow" />
                                <Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" />
                            </Trigger>                            
                            <Trigger Property="IsSelected" Value="False">
                                <Setter TargetName="Border" Property="Background" Value="Green" /> 
                                <Setter Property="Foreground" Value="AliceBlue"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="Border" Property="Background" Value="Orange" />
                                <Setter Property="Foreground" Value="Black"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </TabItem.Style>
</TabItem>

背后的代码是:

public Tab()
        {
            SelectedBgClr = new SolidColorBrush(Colors.Red);
            //UnSelectedBgClr = new SolidColorBrush(Colors.Green);
            //HoverBgClr = new SolidColorBrush(Colors.Orange);
            InitializeComponent();

        }
public static readonly DependencyProperty SelectedBgClrProperty = DependencyProperty.Register("SelectedBgClr", typeof(Brush), typeof(Tab), new UIPropertyMetadata(null));
public Brush SelectedBgClr
{
    get
    {
        return (Brush)GetValue(SelectedBgClrProperty);
    }
    set
    {
        SetValue(SelectedBgClrProperty, value);
    }
}

2 回答

  • 1

    WPF允许您基于现有控件创建新的自定义控件类型,然后可以使用Microsoft站点上的模板/样式声明填充它并更改位以适合您 . 创建一个名为MyTabControl的新用户控件,并用以下代码替换后面的代码:

    public partial class MyTabControl : TabControl
    {
        public static readonly DependencyProperty SelectedBgClrProperty = DependencyProperty.Register("SelectedBgClr",
            typeof(Brush), typeof(MyTabControl), new UIPropertyMetadata(null));
    
        [Category("Appearance")]
        public Brush SelectedBgClr
        {
            get
            {
                return (Brush)GetValue(SelectedBgClrProperty);
            }
            set
            {
                SetValue(SelectedBgClrProperty, value);
            }
        }
    
        public MyTabControl()
        {
            InitializeComponent();
        }
    }
    

    现在用这个替换xaml(您需要将命名空间更改为您的项目):

    <TabControl x:Class="TabDemo.MyTabControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             Name="tabControl"
             d:DesignHeight="300" d:DesignWidth="300">
    
    <TabControl.Resources>
    
        <Style TargetType="{x:Type TabItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabItem}">
                        <Grid>
                            <Border  Name="Border" Margin="0,0,-4,0" BorderThickness="1,1,1,1" CornerRadius="2,12,0,0" >
                                <ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True"/>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="True">
                                <Setter Property="Panel.ZIndex" Value="100" />
                                <Setter TargetName="Border" Property="Background" Value="{Binding ElementName=tabControl, Path=SelectedBgClr}" />
                                <Setter Property="Foreground" Value="Yellow" />
                                <Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" />
                            </Trigger>
                            <Trigger Property="IsSelected" Value="False">
                                <Setter TargetName="Border" Property="Background" Value="Green" />
                                <Setter Property="Foreground" Value="AliceBlue"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="Border" Property="Background" Value="Orange" />
                                <Setter Property="Foreground" Value="Black"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </TabControl.Resources>
    
    <TabControl.Style>
        <Style  TargetType="{x:Type TabControl}">
            <Setter Property="OverridesDefaultStyle"
              Value="True" />
            <Setter Property="SnapsToDevicePixels"
              Value="True" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabControl}">
                        <Grid KeyboardNavigation.TabNavigation="Local">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                    Storyboard.TargetProperty="(Border.BorderBrush).
                        (SolidColorBrush.Color)">
                                                <EasingColorKeyFrame KeyTime="0"
                                             Value="#FFAAAAAA" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <TabPanel x:Name="HeaderPanel"
                        Grid.Row="0"
                        Panel.ZIndex="1"
                        Margin="0,0,4,-1"
                        IsItemsHost="True"
                        KeyboardNavigation.TabIndex="1" />
                            <Border x:Name="Border"
                      Grid.Row="1"
                      BorderThickness="1"
                      CornerRadius="2"
                      KeyboardNavigation.TabNavigation="Local"
                      KeyboardNavigation.DirectionalNavigation="Contained"
                      KeyboardNavigation.TabIndex="2" Background="{Binding ElementName=tabControl, Path=SelectedBgClr}">
                                <ContentPresenter x:Name="PART_SelectedContentHost"
                                  Margin="4"
                                  ContentSource="SelectedContent" />
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </TabControl.Style>
    

    现在在你的MainWindow中,或者只是像常规TabControl一样使用它,SelectedBgClr将设置选定的选项卡 Headers 和主面板背景(如果你在上面的XAML中看到你看到两者的绑定):

    <local:MyTabControl SelectedBgClr="Red">
            <TabItem Header="Foo"  />
            <TabItem Header="Bar" />
            <TabItem Header="Baz" />
        </local:MyTabControl>
    

    请注意,后面的代码是最小的,它仍然是执行大部分工作的XAML,而MyTabControl只是用作依赖项属性的包装器 . 在实际应用程序中,您将使用称为附加属性的东西,这样您就不需要派生一个全新的TabControl类 .

  • 4

    你发现难以得到问题答案的原因是因为你完全以错误的方式解决问题;我可以想到很少的情况,如你所建议的那样改变代码中的控件是合理的 . WPF专门设计用于将视觉状态与代码分离,忽略这一点,这是您自己的危险!

    通过以下方式实际回答您的问题会做的伎俩......有点......

    foreach (TabItem item in tabControl.Items)
        item.Background = new SolidColorBrush(Colors.Blue);
    

    如果您这样做,那么您会注意到它会更改未选定选项卡的背景颜色,但不会更改当前选定的选项卡 . 您还会注意到,使用鼠标突出显示选项卡将再次显示另一种颜色 . TabItem实际上有7种不同的视觉状态,添加代码来覆盖这些案例中的每一种都开始变得混乱,当然比使用XAML要复杂得多 .

    通过代码控制背景颜色的"proper"方式是使用XAML和数据绑定 . 首先转到Microsoft MSDN page for WPF TabControl Styles and Templates,你忘记了添加名称空间和资源 . 如果你在刷子上玩各种资源,你猜测一个布尔值 . 另一个(更好)的方法,并且没有一点点超过"beginner"阶段,你需要提供更多关于你的具体案例的信息 .

    更新:这似乎对我有用:

    void TabSet_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            foreach (TabItem item in tabControl.Items)
                item.Background = new SolidColorBrush(item.IsSelected ? Colors.Green : Colors.Red);
        }
    

    我仍然说这是非常错误的 . 如果您绝对坚持在代码中执行此操作,那么您不应该使用WPF . 这完全是错误的技术,我不能强调这一点!

    更新#2:你几乎就在那里,你只需要在托管标签控件的窗口中执行此操作:

    <Window x:Class="MyWpfApplication.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Window1" Height="300" Width="300" WindowState="Maximized">
    
        <Window.Resources>
    
            <Style TargetType="{x:Type TabItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type TabItem}">
                            <Grid>
                                <Border  Name="Border" Margin="0,0,-4,0" BorderThickness="1,1,1,1" CornerRadius="2,12,0,0" >
                                    <ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True"/>
                                </Border>
                            </Grid>
                            <ControlTemplate.Triggers>
    
                                <Trigger Property="IsSelected" Value="True">
                                    <Setter Property="Panel.ZIndex" Value="100" />
                                    <Setter TargetName="Border" Property="Background" Value="Red" />
                                    <Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" />
                                </Trigger>
    
                                <Trigger Property="IsSelected" Value="False">
                                    <Setter TargetName="Border" Property="Background" Value="Green" />
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter TargetName="Border" Property="Background" Value="Orange" />
                                </Trigger>
    
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
    
        </Window.Resources>
    
        <TabControl>
            <TabItem Header="Foo" />
            <TabItem Header="Bar" />
            <TabItem Header="Baz" />
        </TabControl>
    
    </Window>
    

相关问题