2011-09-06 42 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}"> 
相關問題