WPF TabControl - Выберите другую вкладку при изменении видимости TabItem - PullRequest
8 голосов
/ 26 августа 2010

У меня есть TabControl на UserControl, поддерживаемом ViewModel, и Visibility одного из элементов вкладки привязан к свойству на ViewModel.

<TabControl x:Name="myTabControl">
    <TabItem Header="Tab 1" />
    <TabItem Header="Tab 2" Visibility="{Binding HasData, Converter={StaticResource boolToVisibilityConverter}}"/>
</TabControl>

КогдаVisibility из TabItem изменяется, он сворачивает (скрывает) заголовок TabItem, но продолжает отображать его содержимое.

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

Прикрепление обработчика события к событию SelectionChanged TabControl показывает, что TabItem.IsSelectedTabControl.SelectedItem) даже не изменяется при изменении TabItem.Visibility (это ошибка ?!).

Я пробовал использовать триггер свойства :

    <!-- This doesn't compile because of TargetName on the Setter, think you can only use it in Control Templates.
         I don't know how to refer to the parent TabControl from within the TabItem style. -->
    <TabControl.ItemContainerStyle>
        <Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}">
            <Style.Triggers>
                <Trigger Property="Visibility" Value="Collapsed">
                    <Setter TargetName="myTabControl" Property="SelectedIndex" Value="0" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </TabControl.ItemContainerStyle>

и триггер данных :

    <!-- This doesn't quite work, it affects the Visibility of the TabItem's content too -->
    <TabControl.Style>
        <Style TargetType="{x:Type TabControl}" BasedOn="{StaticResource {x:Type TabControl}}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=SelectedItem.Visibility, ElementName=tabControl}" 
                             Value="Collapsed">
                    <Setter Property="SelectedIndex" Value="0" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TabControl.Style>

Я не могу заставить триггеры работать, и нет никакого события VisibilityChanged, которое я мог бы обработать, поэтому я застрял и был бы признателен за некоторую помощь.

Ответы [ 3 ]

4 голосов
/ 26 августа 2010

Класс TabItem имеет событие IsVisibleChanged, которое вы можете использовать.

2 голосов
/ 27 января 2012

Привязать SelectedIndex TabControl к свойству.И измените значение этого свойства на индекс вкладки, который вы хотите отображать всякий раз, когда вы изменяете видимость свертывания элемента вкладки.

1 голос
/ 19 апреля 2013

Вы можете добавить этот обработчик события к коду позади.Он будет проверять ваш элемент управления в первую очередь и на изменениях видимости вкладок из-за привязок.

Вместо того, чтобы делать это OnLoaded, конечно, имеет смысл поместить это в присоединенное свойство.(Автоматический выбор?) .Код такой же.Во-первых, вам звонят и прикрепляют события к IsVisibleChanged.Тогда единственный трюк - использовать лямбду (привязку параметров), чтобы получить экземпляр TabControl в обратном вызове события.Я публикую это решение, потому что оно короче.

private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e)
{
    var tabControl = (TabControl) sender;
    // register visibility changed to react on changes
    foreach (TabItem item in tabControl.Items)
    {
        item.IsVisibleChanged += (mSender, ev) => item_IsVisibleChanged(mSender, ev, tabControl);
    }
    // if current selected tab is invisible, find and select first visible one.
    if (!((TabItem) tabControl.SelectedItem).IsVisible)
    {
        foreach (TabItem item in tabControl.Items)
        {
            if (item.IsVisible)
            {
                tabControl.SelectedItem = item;
                return;
            }
        }
    }
}

private static void item_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e, TabControl tabControl)
{
    // just became IsVisible = false
    if ((bool)e.NewValue == false)
    {
        if (tabControl == null) return;
        ItemCollection items = tabControl.Items;
        foreach (UIElement item in items)
        {
            if (item.IsVisible)
            {
                tabControl.SelectedItem = item;
                return;
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...