question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Preventing tab changes for TabControl

See original GitHub issue

If we have a TabControl in a WPF application and we’d like to allow or not tab changes, the best way we can actually do it is by having an attached property like the following :

public static partial class TabControlHelper
{
    public static readonly DependencyProperty PreventTabChangeProperty = DependencyProperty.RegisterAttached("PreventTabChange", typeof(bool), typeof(TabControlHelper), new PropertyMetadata(false, OnPreventTabChangeChanged));

    public static bool GetPreventTabChange(TabControl tabControl)
    {
        return (bool)tabControl.GetValue(PreventTabChangeProperty);
    }

    public static void SetPreventTabChange(TabControl tabControl, bool value)
    {
        tabControl.SetValue(PreventTabChangeProperty, value);
    }

    private static void OnPreventTabChangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue is bool preventTabChanges && d is TabControl tabControl)
        {
            if (preventTabChanges)
            {
                tabControl.SelectionChanged += TabControl_SelectionChanged;
            }
            else
            {
                tabControl.SelectionChanged -= TabControl_SelectionChanged;
            }
        }
    }

    private static void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (sender is TabControl tabControl && e.RemovedItems.Count > 0)
        {
            int prevIdx = tabControl.Items.IndexOf(e.RemovedItems[0]);
            if (prevIdx != -1)
            {
                tabControl.SelectionChanged -= TabControl_SelectionChanged;
                tabControl.SelectedIndex = prevIdx;
                tabControl.SelectionChanged += TabControl_SelectionChanged;
            }
        }
    }
}

It prevents tab changes properly but it has side effects : because of tabControl.SelectedIndex = prevIdx;, Selector.SelectionChanged is raised. Moreover the initial tab change won’t be really prevented, it’ll just be reverted and that means the initial Selector.SelectionChanged is also triggered. In the end, the tab change has been properly “prevented” but Selector.SelectionChanged is raised twice which is obviously not what we want.

I’m not sure about what’s the best way to implement this in WPF, I think the most natural to me would be having a boolean dependency property usable like the above attached property but without the side effects or a PreviewSelectionChanged event that allows me to cancel the change via args… As long as tab changes can be prevented without side effects it’s good.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:1
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

3reactions
miloushcommented, May 25, 2021

@Symbai the problem with that is the expectation of routing strategies. SelectionChanged is a bubbling event, and by convention the tunneling counter parts are prefixed with Preview. I would find it very confusing that there would be a tunneling version of the event that you would not find by looking for Preview name.

As for past tense in names, there is Executed and PreviewExecuted events on CommandManager, Got/LostKeyboardFocus and PreviewGot/LostKeyboardFocus etc. There is also ContextMenuOpening/Closing and Copying/Pasting but these are bubbling.

I think should this be added it should be named according to the routing strategy.

2reactions
miloushcommented, May 25, 2021

@Symbai Why would you prefer SelectionChanging to PreviewSelectionChanged?

Either way, this is not a very user-friendly solution. The way to do this is to disable the other tabs, so that user can see that they cannot be activated, and that way no event will be fired in the first place.

Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - TabControl Cancel change of tabs
If you want to cancel the change of a tab, you can use the Deselecting event. There you can cancel the change by...
Read more >
Thread: [RESOLVED] Prevent the user from changing ...
Hi, I have a TabControl in my application. When the application stars the user must decide between two options.
Read more >
How do I prevent the user from changing the selected tab ...
You can use the TabPage's Validating event to prevent a new tab page selection. Here are the steps: 1) Every time the user...
Read more >
Disable the tab page click action in tab control event
Try it like this : C#. public class myTabControl : TabControl { protected override void OnSelecting(TabControlCancelEventArgs e) { e.
Read more >
how do i stop the tabs on a tab control from changing.
i have 2 tabs when i change data on the table tab i check it to make sure that it is correct if...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found