简体   繁体   中英

How to programmatically change selected tabItem Header colour from code behind

I have a program in which I have to load colours at startup. Then I have to add a tabcontrol with tab items:

TabControl tabc = m_Executer.GetTabControl();<---- from outside
if (tabc != null)
{
    TabItem tbi = new TabItem();
    tbi.Header.Background = Brushes.Transparent;
    tbi.Header.Content = "End manager";
    tabc.Items.Add(tbi);
    tabc.SelectionChanged += (sender2, args) =>
    {
        ((TabItem)(tabc.SelectedItem)).Background = Brushes.Red;
        tabc.UpdateLayout();
    };
}

the idea is changing the background when the selectionchanged event is fired but that doesn't work.

The default control template for a TabItem contains two Border elements named "mainBorder" and an "innerBorder". You could change the Background of the latter one:

tabc.SelectionChanged += (sender2, args) =>
{
    if(args.AddedItems != null && args.AddedItems.Count > 0)
    {
        TabItem ti = args.AddedItems[0] as TabItem;
        if(ti != null && VisualTreeHelper.GetChildrenCount(ti) > 0)
        {
            Grid grid = VisualTreeHelper.GetChild(ti, 0) as Grid;
            if (grid != null)
            {
                Border mainBorder = grid.Children[0] as Border;
                if (mainBorder != null)
                {
                    Border innerBorder = mainBorder.Child as Border;
                    if(innerBorder != null)
                        innerBorder.Background = Brushes.Red;
                }
            }
       }
   }
};

The above code works on Windows 10. The templates may differ between different versions of Windows.

If you want to change the background of the unselected TabItem you simply replace AddedItems with RemovedItems and set the Background property of the mainBorder .

You might use a textblock to change color:

TabItem tbi = new TabItem();
tbi.Header = Brushes.Transparent;
TextBlock tbk = new TextBlock() { Text="End manager" };
tbi.Header = tbk;
    tabc.Items.Add(tbi);

and then change the textblock on the event

tabc.SelectionChanged += (sender2, args) =>
{

    ((TabItem)(tabc.SelectedItem)).Foreground = Brushes.Red;
    tabc.UpdateLayout();

};

EDIT you'd better de-highlight the unselected items:

tabc.SelectionChanged += (sender2, args) =>
{
    foreach (var item in tabc.Items)
    {
        if (item == ((TabItem)(tabc.SelectedItem)))
            ((TabItem)item).Foreground = Brushes.Red;
        else
        ((TabItem)item).Foreground = Brushes.Black;
    }                   
};

You have to set the Content to TextBlock instead of a string:

XAML:

<TabControl>
    <TabControl.Items>
        <TabItem >
            <TabItem.Header>
                <TextBlock Background="Red" Text="Foo"/>
            </TabItem.Header>
        </TabItem>
        <TabItem Header="Bar" />
    </TabControl.Items>
</TabControl>

or code behind (for whatever reason...)

TabItem tbi = new TabItem();
TextBlock headerElement = new TextBlock();
headerElement.Text = "End manager";
headerElement.Background = Brushes.Red;
tbi.Header = headerElement;

I also suggest you do take a deep dive into the MVVM pattern. In 98% of the cases it's best practice to write your UIs in XAML and bind to a ViewModel.

BTW: Your code doesn't even compile as Header is of type object ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM