Сделать ленту ContextualTabGroups Показать, когда лента свернута

Ниже приведен сценарий:

Когда лента не свернута, отображается вкладка, связанная с RibbonContextualTabGroup работает нормально, как видно на следующем скриншоте.

Обычная лента

Когда лента свернута, отображается вкладка, связанная с RibbonContextualTabGroup показывает вкладки, но не контекстный заголовок группы вкладок, как видно на следующем снимке экрана.

Минимизированная лента

Если лента свернута, но открыто всплывающее окно с вкладкой, связанной с RibbonContextualTabGroup работает нормально, как видно на следующем скриншоте. (Всплывающее окно не отображается, но я так и создал сценарий.)

Минимизированная лента с открытым всплывающим окном

WebMatrix также имеет эту проблему, поэтому я предполагаю, что разработчики Microsoft намеренно закодировали эту функциональность. Однако в Windows 8/Office 2013 контекстные группы вкладок отображаются всегда, независимо от состояния ленты.

Я использую.NET 4.0 RibbonControlsLibrary от Microsoft, поэтому у меня есть доступ к полному исходному коду. Как изменить код так, чтобы контекстные группы вкладок отображались всегда, независимо от состояния ленты?

3 ответа

Решение

Да, действительно хорошо, большое спасибо, Мин!

Есть ли способ использовать RibbonContextualTabGroupItemsControl.cs без копирования и переопределения всех связанных классов ленты-источника?

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

Существует триггер, который обрабатывает свойство IsMinimized ленты:

<Trigger Property="IsMinimized" Value="True">
    <Setter Property="Content" TargetName="mainItemsPresenterHost" Value="{x:Null}"/>
    <Setter Property="Visibility" TargetName="mainItemsPresenterHost" Value="Collapsed"/>
    <Setter Property="Content" TargetName="popupItemsPresenterHost" Value="{Binding ElementName=groupsBorder}"/>
    <Setter Property="BorderThickness" TargetName="BackgroundBorder" Value="0,0,0,1"/>
</Trigger>

Содержимое mainItemsPresenterHost-control представляет собой границу с именем groupsBorder, которая содержит все вкладки ленты. Когда свойство IsMinimized изменяется на true, эта граница перемещается в презентатор всплывающих окон с именем "popupItemsPresenterHost".

Другой триггер обрабатывает свойство IsDropDownOpen:

<Trigger Property="IsDropDownOpen" Value="True">
    <Setter Property="BorderThickness" TargetName="BackgroundBorder" Value="0"/>
/Trigger>

Я изменил оба триггера следующим образом:

<Trigger Property="IsMinimized" Value="True">
    <!--<Setter Property="Content" TargetName="mainItemsPresenterHost" Value="{x:Null}"/>-->
    <!--<Setter Property="Visibility" TargetName="mainItemsPresenterHost" Value="Collapsed"/>-->
    <Setter Property="Height" TargetName="mainItemsPresenterHost" Value="0"/>
    <!--<Setter Property="Content" TargetName="popupItemsPresenterHost" Value="{Binding ElementName=groupsBorder}"/>-->
    <Setter Property="BorderThickness" TargetName="BackgroundBorder" Value="0,0,0,1"/>
</Trigger>

<Trigger Property="IsDropDownOpen" Value="True">
    <Setter Property="BorderThickness" TargetName="BackgroundBorder" Value="0,0,0,1"/>
    <Setter Property="Content" TargetName="mainItemsPresenterHost" Value="{x:Null}"/>
    <Setter Property="Content" TargetName="popupItemsPresenterHost" Value="{Binding ElementName=groupsBorder}"/>
</Trigger>

Обратите внимание, что я заменил установщик свойства Visibility элемента mainItemsPresenterHost на свойство Height и установил его в "0".

У меня та же проблема, и я нашел этот обходной путь.

  1. Переопределите метод OnApplyTemplate в окне, которому принадлежит лента, чтобы получить RibbonContextualTabGroupItemsControl и установить внутреннее поле:

  2. Установите для свойства IsMinimized ленты значение true, перед тем как установить видимость для контекстной группы видимой, затем вызовите UpdateLayout для RibbonContextualTabGroupItemsControl и сбросьте свойство IsMinimized-Property ленты на false:

Код

...
RibbonContextualTabGroupItemsControl _ribbonContextualTabGroupItemsControl;
...  

public override void OnApplyTemplate()  
{  
    base.OnApplyTemplate();  
    Ribbon ribbon = this.ribbon;  
    ribbon.ApplyTemplate();  
    this._ribbonContextualTabGroupItemsControl = ribbon.Template.FindName("PART_ContextualTabGroupItemsControl", ribbon) as RibbonContextualTabGroupItemsControl;  
}  

...  

void toggleRibbonContextualGroupVisibility()  
{  
    if(this.ribbonContextualGroup.Visibility == Visibility.Collapsed)  
    {
        if (this.ribbon.IsMinimized)  
        {  
            this.ribbon.IsMinimized = false;  
            this.ribbonContextualGroup.Visibility = Visibility.Visible;  
            this._ribbonContextualTabGroupItemsControl.UpdateLayout();  
            this.ribbon.IsMinimized = true;  
        }  
        else  
        {  
            this.ribbonContextualGroup.Visibility = Visibility.Visible;  
        }  
    }
    else  
    {  
        this.ribbonContextualGroup.Visibility = Visibility.Collapsed;
    }
}  

...  

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

После игры с исходными файлами для RibbonControlsLibrary и просто пробного использования метода проб и ошибок я нашел следующее решение:

Откройте RibbonContextualTabGroupItemsControl.cs, расположенный по адресу Microsoft/Windows/Controls/Ribbon, разверните раздел Private Methods #region и найдите функцию HasTabs. Код должен выглядеть примерно так:

private bool HasTabs(FrameworkElement container)
{
    RibbonContextualTabGroup tabGroupHeader = container as RibbonContextualTabGroup;
    if (tabGroupHeader == null ||
        !tabGroupHeader.IsVisible)
    {
        return false;
    }

    foreach (RibbonTab tab in tabGroupHeader.Tabs)
    {
        if (tab != null && tab.IsVisible)
        {
            return true;
        }
    }
    return false;
}

Все, что я добавил, это следующие две строки кода:

if (Ribbon.IsMinimized)
    return true;

Теперь функция должна выглядеть так:

private bool HasTabs(FrameworkElement container)
{
    RibbonContextualTabGroup tabGroupHeader = container as RibbonContextualTabGroup;
    if (tabGroupHeader == null ||
        !tabGroupHeader.IsVisible)
    {
        return false;
    }

    if (Ribbon.IsMinimized)
        return true;

    foreach (RibbonTab tab in tabGroupHeader.Tabs)
    {
        if (tab != null && tab.IsVisible)
        {
            return true;
        }
    }
    return false;
}

Запустите ваше приложение и, наконец, контекстные группы вкладок теперь отображаются, даже если лента свернута.

Обратите внимание, что если у вас нет доступа к исходному коду ленты, использование решения zznobody все равно будет работать на пределе.

Другие вопросы по тегам