I've been pounding away at this issue for a little while, and have only found part of the solution.
I'm trying to set up a TabControl so that I can in some cases prevent the user from changing the currently selected tab. When the user is prevented from changing the currently selected tab, then they are shown a dialog box.
I have already read the following documents:
<ul>
<li><a href="https://stackoverflow.com/questions...tbox-scroll-position-when-itemssource-changes">WPF - reset ListBox scroll position when ItemsSource changes</a></li>
<li><a href="http://wizardsofsmart.net/uncategor...d-event-using-attached-dependency-properties/" rel="nofollow noreferrer">http://wizardsofsmart.net/uncategor...d-event-using-attached-dependency-properties/</a></li>
<li><a href="http://joshsmithonwpf.wordpress.com/2009/09/04/how-to-prevent-a-tabitem-from-being-selected/" rel="nofollow noreferrer">http://joshsmithonwpf.wordpress.com/2009/09/04/how-to-prevent-a-tabitem-from-being-selected/</a></li>
<li><a href="http://social.expression.microsoft.com/Forums/en-US/wpf/thread/f7b46018-1e97-4bbe-ada8-49b75dbc1da2/" rel="nofollow noreferrer">http://social.expression.microsoft.com/Forums/en-US/wpf/thread/f7b46018-1e97-4bbe-ada8-49b75dbc1da2/</a></li>
</ul>
I have implemented the solution indicated in the 3rd link (though all of the above create the same error seen below). And it works, <strong>but</strong>...
Things mess up thoroughly if the user does the following:
<ul>
<li>attempts to change the tab when such an action is disallowed. The MessageBox pops up with the error.</li>
<li>the user clicks "OK" and is returned to the original window.</li>
<li>the user tries again to change the tab. <strong>No MessageBox appears.</strong></li>
<li>if the user minimizes the window, and then maximizes it again, then the MessageBox that was supposed to appear earlier appears.</li>
<li>the user clicks "OK" and is returned to the original window... <strong>but the tab has been changed to the one they selected before, even though they should not be able to change tabs</strong>. </li>
</ul>
This is obviously <strong>not</strong> ideal behavior. <strong>Why isn't the MessageBox appearing the second time, and why is the tab changing when it should be disallowed from doing so?</strong>
If I remove the MessageBox part, it works fine.
Here is the code for the TabControl.SelectionChanged event handler:
I am using MVVM to implement this. The Window looks like this:
I'm omitting the rest of the code for sake of brevity- there is a pretty straight-forward ViewModel structure backing the window.
I'm trying to set up a TabControl so that I can in some cases prevent the user from changing the currently selected tab. When the user is prevented from changing the currently selected tab, then they are shown a dialog box.
I have already read the following documents:
<ul>
<li><a href="https://stackoverflow.com/questions...tbox-scroll-position-when-itemssource-changes">WPF - reset ListBox scroll position when ItemsSource changes</a></li>
<li><a href="http://wizardsofsmart.net/uncategor...d-event-using-attached-dependency-properties/" rel="nofollow noreferrer">http://wizardsofsmart.net/uncategor...d-event-using-attached-dependency-properties/</a></li>
<li><a href="http://joshsmithonwpf.wordpress.com/2009/09/04/how-to-prevent-a-tabitem-from-being-selected/" rel="nofollow noreferrer">http://joshsmithonwpf.wordpress.com/2009/09/04/how-to-prevent-a-tabitem-from-being-selected/</a></li>
<li><a href="http://social.expression.microsoft.com/Forums/en-US/wpf/thread/f7b46018-1e97-4bbe-ada8-49b75dbc1da2/" rel="nofollow noreferrer">http://social.expression.microsoft.com/Forums/en-US/wpf/thread/f7b46018-1e97-4bbe-ada8-49b75dbc1da2/</a></li>
</ul>
I have implemented the solution indicated in the 3rd link (though all of the above create the same error seen below). And it works, <strong>but</strong>...
Things mess up thoroughly if the user does the following:
<ul>
<li>attempts to change the tab when such an action is disallowed. The MessageBox pops up with the error.</li>
<li>the user clicks "OK" and is returned to the original window.</li>
<li>the user tries again to change the tab. <strong>No MessageBox appears.</strong></li>
<li>if the user minimizes the window, and then maximizes it again, then the MessageBox that was supposed to appear earlier appears.</li>
<li>the user clicks "OK" and is returned to the original window... <strong>but the tab has been changed to the one they selected before, even though they should not be able to change tabs</strong>. </li>
</ul>
This is obviously <strong>not</strong> ideal behavior. <strong>Why isn't the MessageBox appearing the second time, and why is the tab changing when it should be disallowed from doing so?</strong>
If I remove the MessageBox part, it works fine.
Here is the code for the TabControl.SelectionChanged event handler:
Code:
bool _isChanging = false;
private void tabControlForNavigation_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!_isChanging && canChangeTabs.IsChecked.HasValue)
{
_isChanging = true;
bool canLeave = canChangeTabs.IsChecked.Value; //normally this would be replaced by a check in the ViewModel
if (!canLeave)
{
int prevIndex = tabControlForNavigation.Items.IndexOf(tabControlForNavigation.SelectedContent);
tabControlForNavigation.SelectedIndex = prevIndex;
MessageBox.Show("Can't change tabs!"); //if I comment out this line, everything works fine.
}
_isChanging = false;
}
}
I am using MVVM to implement this. The Window looks like this:
Code:
<Window x:Class="TestTabControlSwitching.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<CheckBox x:Name="canChangeTabs"
Content="Can Change Tabs"
IsChecked="True" />
<TabControl x:Name="tabControlForNavigation"
Grid.Row="1"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Collection}"
SelectedItem="{Binding SelectedItem}"
SelectionChanged="tabControlForNavigation_SelectionChanged"
Margin="4"
HorizontalAlignment="Stretch">
<TabControl.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Path=Name}" />
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
</Grid>
I'm omitting the rest of the code for sake of brevity- there is a pretty straight-forward ViewModel structure backing the window.