title: How to cancel tab change in WPF TabControl
body: <p>I have found multiple questions about this problem on SO, however I still can't quite get a realiable solution. Here is what I came up with after reading the answers.</p>
  
  <p>Xaml:</p>
  
  <pre><code>&lt;Window x:Class="WpfApplication1.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="300" Width="300" x:Name="this"&gt;
      &lt;TabControl IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Tabs, ElementName=this}" x:Name="TabControl"/&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>Code behind:</p>
  
  <pre><code>public partial class MainWindow : Window
  {
      public MainWindow()
      {
          InitializeComponent();
          var tabs = new ObservableCollection&lt;string&gt; {"Tab1", "Tab2", "Tab3"};
          Tabs = CollectionViewSource.GetDefaultView(tabs);
          Tabs.CurrentChanging += OnCurrentChanging;
          Tabs.CurrentChanged += OnCurrentChanged;
          Tabs.MoveCurrentToFirst();
          CurrentTab = tabs.First();
      }
  
      private void OnCurrentChanging(object sender, CurrentChangingEventArgs e)
      {
          //only show message box when tab is changed by user input
          if (!_cancelTabChange)
          {
              if (MessageBox.Show("Change tab?", "Message", MessageBoxButton.YesNo) == MessageBoxResult.No)
              {
                  _cancelTabChange = true;
                  return;
              }
          }
          _cancelTabChange = false;
      }
  
      private void OnCurrentChanged(object sender, EventArgs e)
      {
          if (!_cancelTabChange)
          {
              //Update current tab property, if user did not cancel transition
              CurrentTab = (string)Tabs.CurrentItem;
          }
          else
          {
              //navigate back to current tab otherwise
              Dispatcher.BeginInvoke(new Action(() =&gt; Tabs.MoveCurrentTo(CurrentTab)));
          }
      }
  
      public string CurrentTab { get; set; }
  
      public static readonly DependencyProperty TabsProperty = DependencyProperty.Register("Tabs", typeof(ICollectionView), typeof(MainWindow), new FrameworkPropertyMetadata(default(ICollectionView)));
      public ICollectionView Tabs
      {
          get { return (ICollectionView)GetValue(TabsProperty); }
          set { SetValue(TabsProperty, value); }
      }
  
      private bool _cancelTabChange;
  }
  </code></pre>
  
  <p>Basically I want to display a confirmation message, when user navigates to different tab, and if he clicks "no" - abort the transition. This code does not work though. If you click multiple times on "Tab2", each time choosing "no" in message box, at some point it stops working: events stop triggering. Event will trigger again if you click on "Tab3", but if you choose "yes" it opens second tab and not third. I am having trouble figuring out wtf is going on. :)</p>
  
  <p>Does anyone see a bug in my solution? Or is there an easier way to display a confirmation message, when user switches tabs? I am also willing to use any opensource tab control, which does have a proper <code>SelectionChanging</code> event. I could not find any though.</p>
  
  <p>I am using .Net 4.0.</p>
  
  <p><strong>Edit:</strong>
  If I comment the message box out:</p>
  
  <pre><code>private void OnCurrentChanging(object sender, CurrentChangingEventArgs e)
  {
      //only show message box when tab is changed by user input
      if (!_cancelTabChange)
      {
          //if (MessageBox.Show("Change tab?", "Message", MessageBoxButton.YesNo) == MessageBoxResult.No)
          //{
              Debug.WriteLine("Canceled");
              _cancelTabChange = true;
              return;
          //}
      }
      _cancelTabChange = false;
  }
  </code></pre>
  
  <p>Everything works fine. Weird.</p>