2011-09-06 40 views
5

我一直在冲击此问题一段时间,只找到部分解决方案。TabControl-阻止用户更改选定的选项卡:导致bug的MessageBox

我想设置一个TabControl,以便在某些情况下可以防止用户更改当前选定的选项卡。当阻止用户更改当前选择的选项卡时,会显示一个对话框。

我已经阅读了以下文件:

我已经实现在第三链接指示的解决方案(尽管所有以上创建相同的错误s见下文)。和它的作品,但...

事情搞糟彻底如果用户执行以下操作:

  • 企图改变标签时,这种行为是不允许的。 MessageBox随着错误弹出。
  • 用户单击“确定”并返回到原始窗口。
  • 用户再次尝试更改选项卡。 不显示消息框。
  • 如果用户最小化窗口,然后再次最大化,那么出现应该出现的消息框。
  • 用户单击“确定”并返回到原始窗口... ,但该标签已更改为之前选择的标签,即使它们不应该能够更改标签

这很明显是不是的理想行为。 为什么MessageBox不会第二次出现,为什么当它不应该这样做时,标签会发生变化?

如果我删除MessageBox部分,它工作正常。

下面是TabControl.SelectionChanged事件处理程序的代码:

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; 
     } 
    } 

我使用MVVM来实现这一点。该窗口看起来是这样的:

<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> 

我忽略了的brevity-缘故代码的其余部分有一个非常直接的视图模型结构支持的窗口。

回答

5

正如您注意到的,问题在于事件处理程序中的MessageBox。重点将改变为MessageBox,你可以得到各种不良影响。我有我自己的问题。

这里是关于同一主题的一对夫妇SO问题
WPF: Does MessageBox Break PreviewMouseDown?
Wpf stop routing event when MessageBox appear?

如果你必须显示一条消息给用户,然后另一种方法可能是创建一个新的Window你的风格像MessageBox,然后在事件处理函数内部调用Show而不是ShowDialog)。

+0

我们知道这是否是WPF中的错误?还是出于某种奇怪的原因“按设计”? – skybluecodeflier

+0

我不确定,在几年前找到了这个原因,但从未找到任何信息。只是用Reflector来看它,但它很复杂,以告诉发生了什么。 –

+0

噢,好吧。你的解决方法是不理想的,但是可行的。不幸的是我需要有某种弹出窗口。 – skybluecodeflier

0

我知道这个帖子是有点老了,但我有一个非常简单的方法来做到这一点:

使用tab_Enter事件,并创建执行您的支票的方法,并显示一个MessageBox给用户,然后设置myTabs.SelectedIndex到先前的指数。一个简单的例子:

private void someTab_Enter(object sender, EventArgs e) 
    { 
     if (myCondition) 
     { 
      MessageBox.Show("Sorry, myCondition will not let you move to this tab."); 
      myTabs.SelectedIndex = someOtherTabIndex; 
     } 
    } 
0

这是一个非常详细的问题。我遇到了同样的问题(即消息框不会在第2或第3个选择中显示,直到您最小化和最大化窗口),并且在进行了大量调试和多次谷歌搜索之后,偶然发现了下面链接的MSDN论坛帖子。

[TabControl SelectionChanged Strange Behaviour?]

请忽略格式混乱的问题和答案。但正如答案中提到的那样,将其放入调度员中,并在设置索引后将选定的选项卡聚焦于解决问题。

0

你错过了一个简单的伎俩。只需为Tab标题设置focusable = False即可。

<TabItem Header="MY TAB" Focusable="False"> 

您可以将此属性绑定到您的视图模型。

<TabItem Header="MY TAB" Focusable="{Binding Bool_CanHasCheeseBurger}"> 
相关问题