WPF: вложенный MenuItems в ToolBar

Из Apple Docs ;

. Примечание

. Монитор Block вызывается для всех будущих событий, соответствующих маске. Вы должны позвонить removeMonitor(_:), чтобы остановить монитор. При сборке мусора монитор (и все, что ссылается на Блок) не будет собираться до тех пор, пока не будет вызван removeMonitor(_:).

blockquote>

Это означает, что монитор будет продолжать поиск совпадающих событий, пока не будет вызвано removeMonitor(). Таким образом, ваша система использует дополнительную память для продолжения поиска событий, и если вы никогда не вызовете это - это может привести к довольно большой утечке памяти. Как говорится даже при сборке мусора, этот объект все еще выделяется - потому что он ищет события, которые могут произойти в любое время (поэтому не гарантируется, что он будет собран). Обязательно звоните, когда хотите, чтобы система перестала искать события.

Вы также можете сделать что-то подобное в вашем handler.

Вы можете вернуть событие без изменения, создать и вернуть новый объект NSEvent или вернуть nil, чтобы остановить отправку события.

BLOCKQUOTE>

9
задан Derek E 21 April 2009 в 06:59
поделиться

3 ответа

Единственный способ, который я мог найти, чтобы даже приблизиться к генерации этого поведения, это создать меню в переполнении, которое содержало бы один пункт меню, заголовок которого сам по себе был другим пунктом меню, называемым «Специальные элементы» и содержащий надлежащие дочерние элементы. Это работало как задумано, но выглядело странно (это можно исправить с помощью пользовательских шаблонов), а также выглядит как огромный взлом. Единственный «правильный» способ сделать это, о котором я могу подумать, - это создать собственный элемент управления, подобный MenuItem, который при наведении вызывает всплывающее окно ContextMenu или Popup, поскольку я не думаю, что пользовательский ControlTemplate может изменить поведение по умолчанию меню, чтобы не требовать щелчка по элементу верхнего уровня.

0
ответ дан 3 November 2019 в 08:21
поделиться

Another solution is to use the existing templates and override the Template for the TopLevelHeader with the Template of the SubmenuHeader.

<Style x:Key="MenuItemStyle" TargetType="{x:Type MenuItem}">
  <Style.Triggers>
    <Trigger Property="Role" Value="TopLevelHeader">
      <Setter Property="Template"
              Value="{StaticResource {x:Static MenuItem.SubmenuHeaderTemplateKey}}"/>
    </Trigger>
  </Style.Triggers> 
</Style>

And use this style in your top level MenuItem. That should simplify your code.

EDIT: You're right, it only works when you click on it (don't know how I convinced myself it worked, sorry :)). It's functionality is like a TopLevelMenu even though the Template says otherwise, its quite confusing.

Only thing I can think of is adding a Trigger to show the Submenu on IsMenuOver and handling the Click event so it does nothing but I don't know how well that would work.

2
ответ дан 3 November 2019 в 08:21
поделиться

После дополнительного чтения я использую решение ниже.

<!-- Resource Dictionary Stuff -->

<!-- Some Brushes -->
<SolidColorBrush x:Key="Brush_1"
    Color="White" />

<LinearGradientBrush x:Key="Brush_2"
    StartPoint="0 0"
    EndPoint="0 1">

    <GradientStop
        Color="White"
        Offset="0"/>

    <GradientStop 
        Color="DarkSeaGreen"
        Offset="1"/>

</LinearGradientBrush>

<SolidColorBrush x:Key="Brush_3"
    Color="DarkOliveGreen"/>

<!-- Custom MenuItem - Top Level Header - Style 1 -->
<Style x:Key="MenuItem_TLH_Style1"
    TargetType="MenuItem">

    <!--<EventSetter Event="PreviewMouseDown" Handler="DoNothing"/>-->

    <Setter Property="Template">
        <Setter.Value>

            <ControlTemplate x:Name="ControlTemplate"
                TargetType="MenuItem">

                <!-- A headered text that may display a submenu
                     on a trigger. This submenu is the host for a
                     menu item's items. -->
                <Border x:Name="BoundaryBorder"
                    Background="{StaticResource Brush_1}"
                    BorderThickness="1">

                    <Grid x:Name="ContainerGrid">

                        <ContentPresenter x:Name="HeaderContent"
                            Margin="6 3 6 3" 
                            ContentSource="Header"
                            RecognizesAccessKey="True"/>

                        <Popup x:Name="SubmenuPopup"
                            Placement="Bottom"
                            IsOpen="{TemplateBinding IsSubmenuOpen}"
                            AllowsTransparency="True"
                            Focusable="False"
                            PopupAnimation="Fade">

                            <Border x:Name="SubmenuBoundaryBorder"
                                SnapsToDevicePixels="True"
                                Background="{StaticResource Brush_1}"
                                BorderBrush="{StaticResource SolidBorderBrush}"
                                BorderThickness="1">

                                <StackPanel x:Name="ItemsStackPanel"
                                    IsItemsHost="True"
                                    KeyboardNavigation.DirectionalNavigation="Cycle"/>

                            </Border>
                        </Popup>
                    </Grid>
                </Border>

                <ControlTemplate.Triggers>

                    <!--  -->
                    <Trigger
                        Property="IsSuspendingPopupAnimation"
                        Value="true">

                        <Setter 
                            TargetName="SubmenuPopup"
                            Property="PopupAnimation"
                            Value="Fade"/>

                    </Trigger>

                    <!-- On mouse-over, show the submenu and highlight the header. -->
                    <Trigger 
                        Property="IsMouseOver"
                        Value="true">

                        <Setter 
                            TargetName="BoundaryBorder"
                            Property="Background"
                            Value="{StaticResource Brush_2}"/>

                        <Setter 
                            TargetName="BoundaryBorder"
                            Property="BorderBrush"
                            Value="{StaticResource Brush_3}"/>

                        <Setter
                            Property="IsSubmenuOpen"
                            Value="true"/>

                        <!-- sloppy? -->
                        <Setter
                            TargetName="SubmenuPopup"
                            Property="IsOpen"
                            Value="true"/>

                    </Trigger>

                    <Trigger 
                        SourceName="SubmenuPopup"
                        Property="AllowsTransparency"
                        Value="true">

                        <Setter 
                            TargetName="SubmenuBoundaryBorder"
                            Property="CornerRadius"
                            Value="0 0 4 4"/>

                        <Setter 
                            TargetName="SubmenuBoundaryBorder"
                            Property="Padding"
                            Value="0 0 0 3"/>

                    </Trigger>

                    <!-- Visually indicate an unaccessible menu item. -->
                    <Trigger
                        Property="IsEnabled"
                        Value="false">

                        <Setter 
                            Property="Foreground"
                            Value="{StaticResource DisabledForegroundBrush}"/>

                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<!-- ... -->

<!-- Inside a window XAML file -->

<!-- Tool Bar Tray -->
<ToolBarTray x:Name="toolBarTray1"
    DockPanel.Dock="Top">

    <!-- File And Edit Tools -->
    <ToolBar x:Name="toolBar1" 
        Band="1" BandIndex="1">

        <!-- Displayed Buttons -->
        <Button x:Name="ButtonA"
            Content="A"/>

        <Button x:Name="ButtonB"
            Content="B"/>

        <!-- Overflow Menu For Special Items -->
        <Menu x:Name="OverflowMenu"
            ToolBar.OverflowMode="Always">

            <MenuItem x:Name="SpecialsMenuItem" 
                Style="{StaticResource MyStyle}"
                Header="Special Items">

                <MenuItem x:Name="CMenuItem"
                    Header="C">

                    <MenuItem x:Name="DMenuItem"
                        Header="D"/>

                </MenuItem>
            </MenuItem>
        </Menu>
    </ToolBar>
</ToolBarTray>

Я атакую ​​поведение SubmenuPopup на наведением мыши, а не обработкой события click. Я хотел бы понять это более полно, поэтому я попытался закомментировать эту часть триггера и добавить обработчик события, который вызывает метод DoNothing () для события PreviewMouseDown. Оказывается, я что-то упускаю и думаю, что это связано с фокусировкой и / или с тем, как меню обрабатывает свою коллекцию элементов. Отсутствие возможности распространения события после «DoNothing ()» (routedEventArgs.Handled = true), по-видимому, устраняет проблемы при нажатии на пункт меню «Специальные элементы». Однако, если кто-то вышел из меню или добавил другой пункт меню, а затем щелкнул по нему, поведение при наведении может быть выключено или включено и выключено.

1
ответ дан 3 November 2019 в 08:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: