TabControl - предотвращение изменения пользователем выбранной вкладки: MessageBox вызывает ошибку - PullRequest
5 голосов
/ 07 сентября 2011

Я некоторое время размышлял над этой проблемой и нашел только часть решения.

Я пытаюсь настроить TabControl, чтобы в некоторых случаях я мог предотвратить изменение пользователем выбранной вкладки.Когда пользователю запрещено изменять выбранную в данный момент вкладку, тогда ему отображается диалоговое окно.

Я уже прочитал следующие документы:

Я реализовал решение, указанное в 3-й ссылке (хотя все вышеперечисленное создает такую ​​же ошибку, как показано ниже).И это работает, , но ...

Если пользователь сделает следующее: все будет очень плохо:

  • пытается изменить вкладку, когда такое действиенеразрешенный.Появляется MessageBox с ошибкой.
  • пользователь нажимает «ОК» и возвращается в исходное окно.
  • пользователь снова пытается изменить вкладку. MessageBox не появляется.
  • если пользователь свернет окно, а затем снова развернет его, появится MessageBox, который должен был появиться раньше.
  • пользователь нажимает "OK "и возвращается в исходное окно ... , но вкладка была изменена на ту, которую они выбирали ранее, даже если они не могут изменять вкладки .

Это, очевидно, не идеальное поведение. Почему 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>

Для краткости я опускаю остальную часть кода - есть довольно простая структура ViewModel, поддерживающая окно.

Ответы [ 4 ]

5 голосов
/ 07 сентября 2011

Как вы заметили, проблема в MessageBox внутри обработчика событий. Фокус изменится на MessageBox, и вы можете получить все виды нежелательных эффектов. У меня были свои проблемы с этим.

Вот пара ТАК вопросов на ту же тему
WPF: MessageBox Break PreviewMouseDown?
Wpf остановить маршрутизацию при появлении MessageBox?

Если вам необходимо отобразить сообщение для пользователя, то альтернативным подходом может быть создание нового Window, который вы стилизуете как MessageBox, а затем вызовите Show ( not ShowDialog ) внутри него в обработчике событий.

0 голосов
/ 12 октября 2015

Вам не хватает простого трюка. Просто сделайте focusable = False для заголовка Tab.

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

Вы можете привязать это свойство к вашей модели представления.

<TabItem Header="MY TAB" Focusable="{Binding Bool_CanHasCheeseBurger}">
0 голосов
/ 05 апреля 2014

Это был очень подробный вопрос. У меня была та же проблема, что и у вас (т. Е. Окно сообщения не отображается при 2-м или 3-м выборе, измененном до тех пор, пока вы не свернули и не развернули окно), и после большой отладки и многочисленных поисков в Google наткнулся на нижеприведенное сообщение на форуме MSDN. *

[TabControl SelectionChanged Странное поведение?]

Пожалуйста, игнорируйте плохо отформатированный вопрос и ответ. Но, как уже упоминалось в ответе, размещение его внутри диспетчера и фокусировка на выбранной вкладке после установки индекса решило проблему для меня.

0 голосов
/ 04 июня 2013

Я знаю, что этот пост немного устарел, но у меня есть очень простой способ сделать это:

Используйте событие 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;
        }
    }
...