Cómo cancelar el cambio de pestaña en WPF TabControl

Nikita B

He encontrado varias preguntas sobre este problema en SO, sin embargo, todavía no puedo obtener una solución confiable. Esto es lo que se me ocurrió después de leer las respuestas.

Xaml:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="300" Width="300" x:Name="this">
    <TabControl IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Tabs, ElementName=this}" x:Name="TabControl"/>
</Window>

Código detrás:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var tabs = new ObservableCollection<string> {"Tab1", "Tab2", "Tab3"};
        Tabs = CollectionViewSource.GetDefaultView(tabs);
        Tabs.CurrentChanging += OnCurrentChanging;
        Tabs.CurrentChanged += OnCurrentChanged;
        Tabs.MoveCurrentToFirst();
        CurrentTab = tabs.First();
    }

    private void OnCurrentChanging(object sender, CurrentChangingEventArgs e)
    {
        //only show message box when tab is changed by user input
        if (!_cancelTabChange)
        {
            if (MessageBox.Show("Change tab?", "Message", MessageBoxButton.YesNo) == MessageBoxResult.No)
            {
                _cancelTabChange = true;
                return;
            }
        }
        _cancelTabChange = false;
    }

    private void OnCurrentChanged(object sender, EventArgs e)
    {
        if (!_cancelTabChange)
        {
            //Update current tab property, if user did not cancel transition
            CurrentTab = (string)Tabs.CurrentItem;
        }
        else
        {
            //navigate back to current tab otherwise
            Dispatcher.BeginInvoke(new Action(() => Tabs.MoveCurrentTo(CurrentTab)));
        }
    }

    public string CurrentTab { get; set; }

    public static readonly DependencyProperty TabsProperty = DependencyProperty.Register("Tabs", typeof(ICollectionView), typeof(MainWindow), new FrameworkPropertyMetadata(default(ICollectionView)));
    public ICollectionView Tabs
    {
        get { return (ICollectionView)GetValue(TabsProperty); }
        set { SetValue(TabsProperty, value); }
    }

    private bool _cancelTabChange;
}

Básicamente, quiero mostrar un mensaje de confirmación cuando el usuario navega a una pestaña diferente y si hace clic en "no", abortar la transición. Sin embargo, este código no funciona. Si hace clic varias veces en "Tab2", cada vez que elige "no" en el cuadro de mensaje, en algún momento deja de funcionar: los eventos dejan de activarse. El evento se activará nuevamente si hace clic en "Tab3", pero si elige "sí", se abre la segunda pestaña y no la tercera. Tengo problemas para averiguar qué está pasando. :)

¿Alguien ve un error en mi solución? ¿O hay una manera más fácil de mostrar un mensaje de confirmación cuando el usuario cambia de pestaña? También estoy dispuesto a usar cualquier control de pestaña de código abierto, que tenga un SelectionChangingevento adecuado . Sin embargo, no pude encontrar ninguno.

Estoy usando .Net 4.0.

Editar: si comento el cuadro de mensaje:

private void OnCurrentChanging(object sender, CurrentChangingEventArgs e)
{
    //only show message box when tab is changed by user input
    if (!_cancelTabChange)
    {
        //if (MessageBox.Show("Change tab?", "Message", MessageBoxButton.YesNo) == MessageBoxResult.No)
        //{
            Debug.WriteLine("Canceled");
            _cancelTabChange = true;
            return;
        //}
    }
    _cancelTabChange = false;
}

Todo funciona bien. Extraño.

Matt Searles

Esta solución http://coderelief.net/2011/11/07/fixing-issynchronizedwithcurrentitem-and-icollectionview-cancel-bug-with-an-attached-property/

parece funcionar bastante bien con

<TabControl ... yournamespace:SelectorAttachedProperties.IsSynchronizedWithCurrentItemFixEnabled="True" .../>

private void OnCurrentChanging(object sender, CurrentChangingEventArgs e)
{                   
    if (MessageBox.Show("Change tab?", "Message", MessageBoxButton.YesNo) == MessageBoxResult.No)
    {
        e.Cancel = true;                    
    }                     
}



public static class SelectorAttachedProperties
{
    private static Type _ownerType = typeof(SelectorAttachedProperties);

    #region IsSynchronizedWithCurrentItemFixEnabled

    public static readonly DependencyProperty IsSynchronizedWithCurrentItemFixEnabledProperty =
        DependencyProperty.RegisterAttached("IsSynchronizedWithCurrentItemFixEnabled", typeof(bool), _ownerType,
        new PropertyMetadata(false, OnIsSynchronizedWithCurrentItemFixEnabledChanged));

    public static bool GetIsSynchronizedWithCurrentItemFixEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsSynchronizedWithCurrentItemFixEnabledProperty);
    }

    public static void SetIsSynchronizedWithCurrentItemFixEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsSynchronizedWithCurrentItemFixEnabledProperty, value);
    }

    private static void OnIsSynchronizedWithCurrentItemFixEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Selector selector = d as Selector;
        if (selector == null || !(e.OldValue is bool && e.NewValue is bool) || e.OldValue == e.NewValue)
            return;

        bool enforceCurrentItemSync = (bool)e.NewValue;
        ICollectionView collectionView = null;

        EventHandler itemsSourceChangedHandler = null;
        itemsSourceChangedHandler = delegate
        {
            collectionView = selector.ItemsSource as ICollectionView;
            if (collectionView == null)
                collectionView = CollectionViewSource.GetDefaultView(selector);
        };

        SelectionChangedEventHandler selectionChangedHanlder = null;
        selectionChangedHanlder = delegate
        {
            if (collectionView == null)
                return;

            if (selector.IsSynchronizedWithCurrentItem == true && selector.SelectedItem != collectionView.CurrentItem)
            {
                selector.IsSynchronizedWithCurrentItem = false;
                selector.SelectedItem = collectionView.CurrentItem;
                selector.IsSynchronizedWithCurrentItem = true;
            }
        };

        if (enforceCurrentItemSync)
        {
            TypeDescriptor.GetProperties(selector)["ItemsSource"].AddValueChanged(selector, itemsSourceChangedHandler);
            selector.SelectionChanged += selectionChangedHanlder;
        }
        else
        {
            TypeDescriptor.GetProperties(selector)["ItemsSource"].RemoveValueChanged(selector, itemsSourceChangedHandler);
            selector.SelectionChanged -= selectionChangedHanlder;
        }
    }

    #endregion IsSynchronizedWithCurrentItemFixEnabled
}

Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.

En caso de infracción, por favor [email protected] Eliminar

Editado en
0

Déjame decir algunas palabras

0Comentarios
Iniciar sesiónRevisión de participación posterior

Artículos relacionados

WPF Caliburn.Micro y TabControl: cambio de pestaña, no cambio de modelo

mantener Recyclerview en el cambio de pestaña

¿Cómo cambio el color de fondo de una página con pestañas en Xamarin iOS?

¿Cómo funciona el cambio de enfoque a través de la pestaña en PyQt5?

¿Cómo cambio el tamaño de la pestaña en Vim?

¿Cómo establecer el estado del menú desplegable en inicial cada vez que cambio de pestaña?

Deshabilite el cambio entre pestañas haciendo clic o teclas en TabControl

¿Cómo eliminar el encabezado de pestaña y estirar TabControl para que no se muestre ningún espacio en blanco?

Evitar el cambio de pestaña en el componente PrimeVue TabView

¿Cómo cambio el color de resaltado de los iconos de la barra de pestañas en Xcode 8?

Cómo cancelar el cierre de la ventana en la aplicación MVVM WPF

Cómo actualizar el contenido de la pestaña después de cambiar de pestaña en wpf mvvm

Cómo detectar el cambio de pestaña desde la página de pestaña activa

NgbTab recarga de componentes en el cambio de pestaña

iOS en el cambio de la barra de pestañas

¿Cómo almaceno el ID de la pestaña actual y cambio a esta pestaña?

Cómo hacer que un control de pestaña llene el centro de un DockPanel en WPF

Android: animar FAB en el cambio de pestaña

Prohibir el cambio de pestaña en un JTabbedPane

¿Puede activar eventos separados en el cambio de pestaña?

Angularjs: ¿cómo cancelar el evento de cambio en el menú desplegable cuando el cuadro de diálogo de confirmación es falso?

¿Cómo cambio el color de desplazamiento de la celda DataGrid en WPF?

¿Cómo usar cellEditEnding o el evento de cambio de celda actual en WPF?

¿Cómo detectar el cambio de contenido de la ventana en WPF?

¿Cómo cancelar el cambio de texto de EditText después de mostrar un mensaje?

¿Cómo cambio el color de la etiqueta en wpf usando vb?

¿Cómo cambio el formato de fecha al editar una fecha en un WPF Datagrid?

Haga clic en la pestaña actual Elemento de TabControl (en WPF)

recargar datos en TabItem desde otra ventana al cambiar de pestaña en tabcontrol WPF

TOP Lista

  1. 1

    ¿Cómo ocultar la aplicación web de los robots de búsqueda? (ASP.NET)

  2. 2

    Pandas의 CSV 파일을 Pandas 데이터 프레임으로 가져 오기

  3. 3

    uitableview delete button image in iOS

  4. 4

    Manera correcta de agregar referencias al proyecto C # de modo que sean compatibles con el control de versiones

  5. 5

    Swift / Firebase : Facebook 사용자가 계정을 만들 때 Firebase 데이터베이스에 제대로 저장하려면 어떻게해야합니까?

  6. 6

    caída condicional de filas desde un marco de datos de pandas

  7. 7

    Link library in Visual Studio, why two different ways?

  8. 8

    Pagination class not getting applied in html

  9. 9

    Que signifie Decimal (-1)?

  10. 10

    UIButton textLabel with different fonts

  11. 11

    WPF pleine largeur DataGridColumn sur la largeur de DataGrid

  12. 12

    Opción de máquina virtual no reconocida 'MaxPermSize = 512m' cuando se ejecuta Zeppelin

  13. 13

    matplotlib로 그래프를 그리는 동안 커서 위치에서 날짜 / 시간을 볼 수 없습니다. "DateFormatter에서 x = 0 값을 찾았습니다"라는 오류가 발생합니다.

  14. 14

    ¿Es posible en Windows evitar que otras aplicaciones se enganchen en las DLL del sistema?

  15. 15

    Error de la base de datos de Android Firebase: Permiso denegado al depurar en un teléfono

  16. 16

    Pandas: suma filas de DataFrame para columnas dadas

  17. 17

    ggplot2: gráfico con líneas y puntos para problemas de leyenda de dos conjuntos de datos

  18. 18

    ¿Cómo especificar el puerto en el que se aloja una aplicación ASP.NET Core?

  19. 19

    Recherche de la position d'index d'une valeur dans r dataframe

  20. 20

    GPU를 사용하여 ffmpeg 필터의 처리 속도를 가속화하는 방법은 무엇입니까?

  21. 21

    nested observables executed one after the other after termination

CalienteEtiquetas

Archivo