Как программно выбрать TabItem в WPF TabControl

Я хотел бы знать, как выбрать конкретный TabItem в WPF TabControl.

Я пробовал это, но ничего не работало!

MyTabControl.SelectedIndex = x

MyTabControl.SelectedItem = MyTabItem

MyTabControl.SelectedValue = MyTabItem

MyTabItem.IsSelected = True

person Pierre Toutant    schedule 28.10.2011    source источник


Ответы (8)


Как говорит @Chris, любая из первых трех вещей должна работать, и, как говорит @Phyxx, это не всегда действительно работает. Проблема заключается в некоторой тонкости порядка изменения свойств. Чтобы обойти это, вам нужно позволить WPF вызывать ваш код выбора вкладки в свое время:

Dispatcher.BeginInvoke((Action)(() => MyTabControl.SelectedIndex = x));

Это делает то же самое, что и таймер Phyxx, но немного менее экстремальным образом.

person Adrian Ratnapala    schedule 21.09.2014
comment
Но почему так? Предложение сработало отлично (+1), но я не могу перестать опасаться, что это только скрывает проблему, которая скрыта за спиной. Выбирая между мной, делающим что-то вопиюще неправильно, и разработчиком Microsoft, делающим что-то вопиюще неправильно, я выбрал самого безопасного коня - меня. - person Konrad Viltersten; 21.01.2015
comment
Мое предположение: разработки MS ошибаются, но не явно. WPF - это сложный и нечеткий API, и, похоже, нет единственного правильного способа его использовать. В результате вы обязательно создадите ситуацию, которую MS не ожидала и не защитила. В этом случае мы каким-то образом устанавливаем поле либо слишком поздно (поэтому оно игнорируется), либо слишком рано (поэтому оно перезаписывается). Никто, даже Microsoft, не знает, сколько сейчас времени. - person Adrian Ratnapala; 21.01.2015
comment
Если это успокаивает ваши нервы - совершенно нормально вызывать диспетчера для некоторых действий пользовательского интерфейса WPF, на самом деле это лучший способ убедиться, что это происходит в нужное время и в нужной среде. Это особенно актуально для многопоточных приложений или когда вы используете Задачи. Ответ Адриана следует отметить как ответ - он самый правильный. - person Digifaktur; 26.01.2015
comment
@Digifaktur, это тоже почти успокаивает мои нервы. Я был слишком резок по отношению к Microsoft; Фреймворки GUI сложны, потому что все потенциально получают уведомления обо всем остальном в неизвестном порядке. Меня устраивает Dispatcher.*Invoke для переключения кода между потоками, но я нервничаю, когда мне приходится использовать его вслепую в одном потоке только потому, что я не понимаю, что происходит. - person Adrian Ratnapala; 26.01.2015
comment
Хорошие моменты / обсуждение, +1. Мне также не нравится идея Dispatcher, которая похожа на потоки на другой путь инструкций, когда он просто должен иметь возможность принимать ту же инструкцию в основной строке. Но это возможно, как сказал Адриан - он вызывается слишком рано, а более поздние команды перезаписывают его - он вызывается слишком поздно, и получатель не знает, что делать. Звучит как плохой дизайн со стороны MS, чтобы иметь такое отключение, но угадайте, это то, с чем мы застряли. - person vapcguy; 22.09.2016
comment
Это обсуждение имеет параллель с программированием графики в браузере: иногда вызов setTimeout с задержкой 0 - это лучший вариант для того, что вы хотите выполнить, даже если JavaScript является однопоточным. Когда вы понимаете, как работает планировщик событий JavaScript, на самом деле все это имеет смысл. Держу пари, что кто-то в MS действительно знает, зачем это нужно. - person jpaugh; 13.08.2019

Все ваши примеры, кроме третьего, верны и будут работать. Проблема должна быть в другом месте. Может ты сбросил пункт после настройки или твой код никогда не вызывается?

Действительно

MyTabControl.SelectedIndex = x   
MyTabControl.SelectedItem = MyTabItem    
MyTabItem.IsSelected = True 

Недействительно

MyTabControl.SelectedValue = MyTabItem 
person HCL    schedule 28.10.2011

Прокрутите элементы вкладок и для выбора вкладки установите

tabItem.IsSelected = true

Если есть другое место из-за смены привязки, вы увидите проблему. В противном случае приведенный выше код должен работать.

person kishhr    schedule 03.06.2012
comment
Ага. Это мне помогло. Это должен быть правильный ответ. - person Mosquito Mike; 19.08.2015

Одна вещь, о которой не упоминалось выше:

Основная причина, по которой что-то подобное не работает, заключается в том, что для элементов вкладок не задано свойство «Имя». Каждый элемент вкладки элемента управления вкладкой, к которому вы хотите перейти программно, должен иметь свойство name, установленное для работы любого из приведенного выше кода.

<tabItem Name="tab1"></tabItem>
person user2976441    schedule 10.11.2013
comment
Это сработало для меня. На динамически создаваемых вкладках ни один из методов, который должен работать, не работал. Я добавил им имена, и они начали работать как положено. - person Craig Neil Brown; 26.03.2015

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

  1. определить свойство в вашей модели представления - выбранный тип int

  2. привязать собственность в вашем представлении

    <TabControl
        x:Name="TabsCandidate" 
        VerticalAlignment="Stretch" 
        TabStripPlacement="Top"
        SelectedIndex="{Binding Selected}"
    
  3. частный int _selected;

    public int Selected
    {
        get { return _selected; }
        set
        {
            _selected = value;
            OnPropertyChanged("Selected");
        }
    }
    
  4. Установите значение свойства Выбрать, просто привязка активирует панель вкладок.

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

    // set the property value of the view model which points the index of the tab controller.
    ((CandidateViewModel)((System.Windows.FrameworkElement)candidateTab.Content).DataContext).Selected = CandidateLogTabIndex;
    
person Shanjee    schedule 13.07.2017
comment
Это позволило мне выбрать нужную вкладку при использовании MVVM. - person AndyUK; 21.01.2019

Попробуйте установить MyTabControl.SelectedIndex = x в обработчике событий DataContextChanged или Loaded вашего пользовательского интерфейса. Надеюсь, это сработает.

person Debasis    schedule 28.10.2011

Я перепробовал все методы, которые должны работать, но, как и вы, на самом деле ничего не изменило выбранную вкладку. В конце концов я заставил его работать, поместив код выбора вкладки в DispatcherTimer галочку.

       DispatcherTimer switchTabTimer = new DispatcherTimer();
       switchTabTimer.Interval = new TimeSpan(0);
       switchTabTimer.Tick += (object timerSender, EventArgs timerE) =>
       {
           myTabControl.SelectedIndex = 0;
           switchTabTimer.Stop();
       };
       switchTabTimer.Start(); 
person Phyxx    schedule 26.12.2013

если вы не знаете индекс вкладки (укажите не TabIndex), используйте:

    private async Task ChangeTabTo(TabItem wantedTab) {
        int index = 0;
        for (var i = 0; i < TabControl.Items.Count; i++) {
            var tab = TabControl.Items[i];
            var t = tab as TabItem;
            if (t == null) continue;
            if (t == wantedTab) {
                index = i;
                break;
            }
        }

        await Dispatcher.BeginInvoke((Action)(() => TabControl.SelectedIndex = index));
    }

или измените его для поиска по имени, если вы не хотите сохранять ссылку на вкладку

person GreyCloud    schedule 09.01.2019