2011-09-06 17 views
5

He estado hablando mucho sobre este tema por un tiempo, y solo he encontrado parte de la solución.TabControl - evitando que el usuario cambie la pestaña seleccionada: MessageBox causando el error

Estoy intentando configurar un TabControl para evitar, en algunos casos, que el usuario cambie la pestaña actualmente seleccionada. Cuando el usuario no puede cambiar la pestaña seleccionada actualmente, se le muestra un cuadro de diálogo.

que ya han leído los siguientes documentos:

he implementado la solución indicada en la tercera enlace (aunque todos de los anteriores crean el mismo error m een abajo). Y funciona, pero ...

echar las cosas a fondo si el usuario hace lo siguiente:

  • intentos de cambiar la pestaña cuando se ha anulado tal acción. El MessageBox aparece con el error.
  • el usuario hace clic en "Aceptar" y regresa a la ventana original.
  • el usuario intenta nuevamente cambiar la pestaña. No aparece MessageBox.
  • si el usuario minimiza la ventana y luego la maximiza de nuevo, aparece el MessageBox que se suponía que debía aparecer antes.
  • el usuario hace clic en "Aceptar" y regresa a la ventana original ... pero la pestaña se ha cambiado a la que seleccionaron antes, aunque no deberían poder cambiar las pestañas.

Esto es obviamente no comportamiento ideal. ¿Por qué no aparece el MessageBox por segunda vez, y por qué está cambiando la pestaña cuando no debería permitirse?

Si elimino la parte de MessageBox, funciona bien.

Este es el código del controlador de eventos 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; 
     } 
    } 

estoy usando MVVM para implementar esto. La ventana se ve así:

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

estoy omitiendo el resto del código en aras de brevity- hay una estructura modelo de vista bastante recta hacia adelante el respaldo de la ventana.

Respuesta

5

Como habrás notado, el problema es MessageBox dentro del controlador de eventos. El enfoque cambiará al MessageBox y podrá obtener todo tipo de efectos no deseados. He tenido mis propios problemas con esto.

Aquí hay un par de pregunta para que sobre el mismo tema
WPF: Does MessageBox Break PreviewMouseDown?
Wpf stop routing event when MessageBox appear?

Si debe mostrar un mensaje al usuario a continuación, un enfoque alternativo podría ser la creación de un nuevo Window que el estilo como una MessageBox y luego llame al Show (noShowDialog) en él dentro del controlador de eventos.

+0

¿Sabemos si esto es un error en WPF? ¿O es por alguna extraña razón "por diseño"? – skybluecodeflier

+0

No estoy seguro, busqué la razón de esto hace un par de años pero nunca encontré ninguna información. Acabo de verlo con Reflector pero es complejo decir qué está pasando. –

+0

Oh bien. Su trabajo no es ideal, pero factible. Desafortunadamente necesito tener algún tipo de ventana emergente. – skybluecodeflier

0

Sé que este post es un poco viejo, pero tengo una manera muy fácil de lograr esto:

utilizar el evento tab_Enter y crear un método que realiza su cheque y muestra una MessageBox al usuario y luego establecer myTabs.SelectedIndex al índice anterior. Un simple ejemplo:

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

Esta fue una pregunta muy detallada. Tuve el mismo problema que tenía (es decir, el cuadro de mensaje no se muestra en la 2ª o 3ª selección modificada hasta que minimiza y maximiza la ventana) y después de mucha depuración y múltiples búsquedas de Google, tropecé con la publicación del foro de MSDN enlazada a continuación.

[TabControl SelectionChanged Strange Behaviour?]

por favor, ignora la pregunta mal formateado y respuesta. Pero como se menciona en la respuesta, ponerlo dentro de un despachador y enfocar la pestaña seleccionada después de configurar el índice resolvió el problema para mí.

0

Faltan un truco fácil. Simplemente haz enfocable = Falso para el encabezado de la pestaña.

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

Puede enlazar esta propiedad a su modelo de vista.

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