2011-09-06 18 views
5

Tôi đã ngừng phát hành vấn đề này một lúc và chỉ tìm thấy một phần của giải pháp.TabControl- ngăn cản người dùng thay đổi tab đã chọn: MessageBox gây lỗi

Tôi đang cố gắng thiết lập TabControl để tôi có thể trong một số trường hợp ngăn người dùng thay đổi tab hiện được chọn. Khi người dùng bị ngăn thay đổi tab hiện đang được chọn, khi đó họ được hiển thị một hộp thoại.

Tôi đã đọc các tài liệu sau:

tôi đã thực hiện các giải pháp đã nêu trong các liên kết thứ 3 (mặc dù tất cả ở trên tạo ra cùng một lỗi een dưới đây). Và nó hoạt động, nhưng ...

Mọi thứ lộn xộn lên triệt để nếu người dùng nào sau đây:

  • nỗ lực để thay đổi tab khi một hành động như vậy là không được phép. MessageBox bật lên với lỗi.
  • người dùng nhấp "OK" và được trả lại cửa sổ ban đầu.
  • người dùng thử lại để thay đổi tab. Không có MessageBox nào xuất hiện.
  • nếu người dùng thu nhỏ cửa sổ và sau đó phóng to lại cửa sổ, thì Hộp thư được cho là xuất hiện trước đó sẽ xuất hiện.
  • người dùng nhấp "OK" và được trả lại cửa sổ gốc ... nhưng tab đã được thay đổi thành tab trước đây, mặc dù họ không thể thay đổi tab.

Điều này rõ ràng là không hành vi lý tưởng. Tại sao MessageBox không xuất hiện lần thứ hai và tại sao tab lại thay đổi khi không được phép làm như vậy?

Nếu tôi xóa phần MessageBox, nó hoạt động tốt.

Đây là mã cho xử lý sự kiện 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; 
     } 
    } 

Tôi đang sử dụng MVVM để thực hiện điều này. Window trông như thế này:

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

tôi bỏ qua phần còn lại của mã cho lợi ích của brevity- có một cấu trúc ViewModel khá thẳng về phía trước sao lưu các cửa sổ.

Trả lời

5

Khi bạn nhận thấy, sự cố là MessageBox bên trong trình xử lý sự kiện. Tiêu điểm sẽ thay đổi thành MessageBox và bạn có thể nhận được tất cả các loại hiệu ứng không mong muốn. Tôi đã có vấn đề của riêng tôi với điều này.

Dưới đây là một vài SO câu hỏi về cùng một chủ đề
WPF: Does MessageBox Break PreviewMouseDown?
Wpf stop routing event when MessageBox appear?

Nếu bạn phải hiển thị một thông điệp tới người dùng sau đó một cách tiếp cận thay thế có thể để tạo ra một mới Window mà bạn phong cách giống như một MessageBox và sau đó gọi Show (khôngShowDialog) vào bên trong trình xử lý sự kiện.

+0

Chúng tôi có biết đây có phải là lỗi trong WPF không? Hay là vì một lý do kỳ lạ nào đó "do thiết kế"? – skybluecodeflier

+0

Tôi không chắc chắn, tìm kiếm lý do cho điều này bản thân mình một vài năm trở lại nhưng không bao giờ tìm thấy bất kỳ thông tin. Chỉ cần nhìn vào nó với Reflector nhưng nó phức tạp để nói những gì đang xảy ra .. –

+0

Oh well. Công việc của bạn là không lý tưởng, nhưng có thể làm được. Thật không may tôi cần phải có một số loại cửa sổ pop-up. – skybluecodeflier

0

Tôi biết bài này là một chút cũ, nhưng tôi có một cách rất dễ dàng để thực hiện điều này:

Sử dụng các sự kiện tab_Enter và tạo ra một phương pháp mà thực hiện kiểm tra của bạn và hiển thị một MessageBox cho người sử dụng và sau đó thiết lập myTabs.SelectedIndex đến chỉ mục trước. Một ví dụ đơn giản:

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

Đây là một câu hỏi rất chi tiết. Tôi đã gặp vấn đề tương tự (tức là hộp thông báo không hiển thị trên lựa chọn thứ 2 hoặc thứ 3 đã thay đổi cho đến khi bạn thu nhỏ và phóng to cửa sổ) và sau nhiều lần gỡ lỗi và tìm kiếm nhiều google, tình cờ gặp bài đăng trên diễn đàn MSDN được liên kết bên dưới.

[TabControl SelectionChanged Strange Behaviour?]

Vui lòng bỏ qua câu hỏi và câu trả lời được định dạng kém. Nhưng như đã đề cập trong câu trả lời, đặt nó bên trong một điều phối viên và tập trung vào tab đã chọn sau khi thiết lập chỉ mục giải quyết vấn đề cho tôi.

0

Bạn đang bỏ lỡ một mẹo dễ dàng. Chỉ cần đặt tiêu điểm = False cho tiêu đề Tab.

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

Bạn có thể liên kết thuộc tính này với mô hình chế độ xem của mình.

<TabItem Header="MY TAB" Focusable="{Binding Bool_CanHasCheeseBurger}">