SharedSizeGroup не работает между MenuItem и Separator - PullRequest
0 голосов
/ 12 марта 2020

Что случилось до сих пор

Я успешно разработал / шаблон ContextMenu и MenuItem для удовлетворения моих потребностей. В частности, мой подход использует совместное использование свойств определения размера между сетками (Grid.IsSharedSizeScope). Ничего особенного; в основном это просто настройка столбцов для иконки, заголовка, текста для ввода и т. д. c. в каждом MenuItem и делиться ими друг с другом.

Стиль для ContextMenu

<Style TargetType="{x:Type ContextMenu}">

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ContextMenu}">

                <Border x:Name="PART_Border"
                        Background="White" BorderBrush="Gray" BorderThickness="1">

                    <StackPanel x:Name="PART_ItemsHost"
                                IsItemsHost="True" Grid.IsSharedSizeScope="True"
                                KeyboardNavigation.DirectionalNavigation="Cycle"/>

                </Border>

            </ControlTemplate>
        </Setter.Value>
    </Setter>

</Style>

Обратите внимание, что я установил Grid.IsSharedSizeScope="True" на StackPanel в котором находится MenuItems.

Шаблон управления для элементов подменю

<ControlTemplate x:Key="{x:Static MenuItem.SubmenuItemTemplateKey}" TargetType="{x:Type MenuItem}">

    <Border x:Name="PART_Border" MinHeight="28" Padding="0 8 0 8" Background="Transparent">

        <Grid x:Name="PART_Grid" VerticalAlignment="Center">

            <Grid.ColumnDefinitions>

                <!-- Column 0: Left padding -->
                <ColumnDefinition Width="13"/>

                <!-- Column 1: Icon -->
                <ColumnDefinition Width="Auto" SharedSizeGroup="Icon"/>

                <!-- Column 2: Header margin -->
                <ColumnDefinition Width="10"/>

                <!-- Column 3: Header -->
                <ColumnDefinition Width="Auto" SharedSizeGroup="Header"/>

                <!-- Column 4: Shortcut -->
                <ColumnDefinition Width="Auto" SharedSizeGroup="Shortcut"/>

                <!-- Column 5: Placeholder for arrow -->
                <ColumnDefinition Width="Auto" SharedSizeGroup="Arrow"/>

                <!-- Column 6: Right padding -->
                <ColumnDefinition Width="13"/>

            </Grid.ColumnDefinitions>

            <!-- Skipping ContentPresenters for icon, header and shortcut... -->

        </Grid>

    </Border>

</ControlTemplate>

Обратите внимание, что я определил SharedSizeGroup для каждого столбца. Область для совместного использования информации о размере является родительской StackPanel в ContextMenu (см. Выше).

Шаблон управления для заголовков подменю

<ControlTemplate x:Key="{x:Static MenuItem.SubmenuHeaderTemplateKey}" TargetType="{x:Type MenuItem}">

    <Border x:Name="PART_Border" MinHeight="28" Padding="0 8 0 8" Background="Transparent">

        <Grid x:Name="PART_Grid" VerticalAlignment="Center">

            <Grid.ColumnDefinitions>

                <!-- Column 0: Left padding -->
                <ColumnDefinition Width="13"/>

                <!-- Column 1: Icon -->
                <ColumnDefinition Width="Auto" SharedSizeGroup="Icon"/>

                <!-- Column 2: Header margin -->
                <ColumnDefinition Width="10"/>

                <!-- Column 3: Header -->
                <ColumnDefinition Width="Auto" SharedSizeGroup="Header"/>

                <!-- Column 4: Shortcut -->
                <ColumnDefinition Width="Auto" SharedSizeGroup="Shortcut"/>

                <!-- Column 5: Arrow -->
                <ColumnDefinition Width="Auto" SharedSizeGroup="Arrow"/>

                <!-- Column 6: Right padding -->
                <ColumnDefinition Width="13"/>

            </Grid.ColumnDefinitions>

            <!-- Skipping ContentPresenters for icon, header and shortcut... -->
            <!-- Skipping visual for submenu arrow... -->

            <Popup x:Name="PART_Popup"
                   Placement="Right" PlacementTarget="{Binding ElementName=PART_Border}"
                   HorizontalOffset="0" VerticalOffset="-1"
                   IsOpen="{TemplateBinding IsSubmenuOpen}"
                   PopupAnimation="Fade" AllowsTransparency="True"
                   Focusable="False">

                <Border x:Name="PART_SubmenuBorder"
                        BorderBrush="Gray" BorderThickness="1" Background="White"
                        SnapsToDevicePixels="True">

                    <StackPanel x:Name="PART_SubmenuItemsHost" IsItemsHost="True"
                                KeyboardNavigation.DirectionalNavigation="Cycle"
                                Grid.IsSharedSizeScope="True"/>

                </Border>

            </Popup>

        </Grid>

    </Border>

</ControlTemplate>

Примечание что я определил те же столбцы, что и для пунктов подменю, включая идентичные SharedSizeGroup для каждого столбца. Область для совместного использования информации о размере, опять же, является родительской StackPanel в ContextMenu. Кроме того, я установил Grid.IsSharedSizeScope="True" на StackPanel, в котором находится MenuItems подменю. Таким образом, каждое подменю имеет свою собственную область для обмена информацией о размере. Большой! :)

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

Где я хочу go далее

С разделением по размеру, настроенным успешно (ура!), Я был убежден, что стилизация / шаблонирование Separator между пунктами контекстного меню было бы просто. Итак, мой подход был такой:

<ControlTemplate x:Key="SubmenuSeparatorTemplate" TargetType="{x:Type Separator}">

    <Grid>

        <Grid.ColumnDefinitions>

            <!-- Column 0: Left padding -->
            <ColumnDefinition Width="13"/>

            <!-- Column 1: Icon -->
            <ColumnDefinition Width="Auto" SharedSizeGroup="Icon"/>

            <!-- Column 2: Header margin -->
            <ColumnDefinition Width="10"/>

            <!-- Column 3: Header -->
            <ColumnDefinition Width="Auto" SharedSizeGroup="Header"/>

            <!-- Column 4: Shortcut -->
            <ColumnDefinition Width="Auto" SharedSizeGroup="Shortcut" />

            <!-- Column 5: Arrow -->
            <ColumnDefinition Width="Auto" SharedSizeGroup="Arrow" />

            <!-- Column 6: Right padding -->
            <ColumnDefinition Width="13"/>

        </Grid.ColumnDefinitions>         

        <Rectangle Grid.Column="3" Grid.ColumnSpan="4" Height="1" Fill="Gray"/>

    </Grid>

</ControlTemplate>

<!-- Style for separators between menu items -->
<Style x:Key="{x:Static MenuItem.SeparatorStyleKey}" TargetType="{x:Type Separator}">
    <Setter Property="Template" Value="{StaticResource SubmenuSeparatorTemplate}"/>
</Style>

Возможно, вы выяснили, что я хочу нарисовать линию, начиная со столбца заголовка до самого правого края пункта меню. Тем не менее, это на самом деле не работает. Хотя совместное использование размера между MenuItems все еще ведет себя как требуется, совместное использование информации о размере с Separator кажется нарушенным. Я ожидал, что оба типа смогут это сделать, поскольку они находятся в одной области общего доступа, а именно StackPanel в шаблоне ContextMenu. Но все, что я получаю, это неправильно выровненная и слишком короткая строка.

Как видите, я намеренно определил шаблон элемента управления вне стиля, так что все шаблоны элемента управления находятся на одном уровне - но, очевидно, это не проблема.

Я что-то упускаю здесь действительно очевидное? Буду признателен за любую помощь!

Как всегда, большое спасибо заранее!

...