2009-04-10 80 views
9

我工作的一些XAML的WPF應用程序,我有一些麻煩它做我想做的。這是我的XAML的一個樣本:WPF:嵌套的MenuItems在工具欄

<!-- Tool Bar Tray --> 
<ToolBarTray Name="toolBarTray1" DockPanel.Dock="Top"> 
    <!-- File And Edit Tools --> 
    <ToolBar Name="toolBar1" Band="1" BandIndex="1"> 
     <!-- Regular Items --> 
     <Button>A</Button> 
     <Button>B</Button> 
     <!-- Overflow Menu For Special Items --> 
     <MenuItem ToolBar.OverflowMode="Always" Header="Special Items"> 
      <MenuItem Header="C"/> 
      <MenuItem Header="D"/> 
     </MenuItem> 
    </ToolBar> 
</ToolBarTray> 

當我點擊我的工具欄的溢出按鈕,「特殊項目」菜單項出現一個小箭頭旁邊,表示嵌套的元素。但是,當我將鼠標懸停在「特殊項目」上或嘗試單擊它時,MenuItems「C」和「D」未顯示。

我希望菜單項將只是一個菜單之外的工作,但我試着做了直接的東西,以防萬一。在菜單中包含這些MenuItems,而是給這個菜單ToolBar.OverflowMode =「Always」屬性會產生一些不需要的樣式。箭頭不再存在,需要點擊「特殊項目」條目來激活子菜單,並且子菜單定位看起來有點偏離。

有誰知道發生了什麼事?

編輯:添加到溢出菜單生產正是我要求(大驚喜)。我所追求的是將頂級標題和項目轉換爲子菜單級別的方法。我已轉向MSDN上的此控制模板示例以獲取解決方案(見下文)。

編輯,編輯: @gcores(註釋討論):真的嗎?我錯過了什麼嗎?

<ToolBar Name="toolBar1" Band="1" BandIndex="4"> 
    <!-- Displayed Buttons --> 
    <Button>A</Button> 
    <Button>B</Button> 
    <!-- Special Items Menu --> 
    <Menu ToolBar.OverflowMode="Always" > 
     <MenuItem Style="{StaticResource MenuItemStyle}" Header="Special"> 
      <MenuItem Header="C"/> 
      <MenuItem Header="D"/> 
     </MenuItem> 
    </Menu> 
</ToolBar> 

這段代碼對我不起作用。我必須點擊'Special'才能顯示子菜單。

回答

0

我能找到,甚至接近產生這種行爲的唯一辦法是創造一個包含其標題本身就是所謂的「特殊項目」,並含有正常的孩子另一個菜單項的單個菜單項溢出的菜單。它按預期工作,但看起來奇怪(這可以通過自定義模板來彌補),也似乎是一個巨大的黑客攻擊。我能想到的唯一「正確」方法是製作自己的MenuItem類控件,它在彈出時彈出一個ContextMenu或Popup,因爲我不認爲自定義ControlTemplate可以更改默認行爲一個菜單,以免需要點擊頂層項目。

1

更多閱讀後,我使用的解決方案如下。

<!-- 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事件。我想更全面地理解這一點,所以我嘗試評論觸發器的這一部分,並添加一個事件處理函數,它在'PreviewMouseDown'事件中調用'DoNothing()'方法。事實證明,我錯過了一些東西,我認爲這與聚焦和/或菜單如何處理其項目集合有關。 'DoNothing()'(routedEventArgs.Handled = true)之後不允許事件傳播似乎消除了單擊「特殊項目」菜單項時出現的問題。但是,如果從菜單導航或添加了另一個菜單項並單擊該項,則可以關閉懸停行爲或打開和關閉懸停行爲。

2

另一種解決方案是使用現有的模板和覆蓋模板與SubmenuHeader的模板的TopLevelHeader。

<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> 

並在頂級MenuItem中使用此樣式。這應該簡化你的代碼。

編輯: 你是對的,它只適用於你點擊它(不知道我是如何說服自己它的工作,對不起:))。 它的功能就像是一個TopLevelMenu,即使模板另有說明,它也相當混亂。

我唯一能想到的就是添加一個觸發器來顯示IsMenuOver上的子菜單並處理Click事件,所以它什麼也不做,但我不知道它會如何工作。

+0

你知道,這正是我一開始想要做的。我在細讀MSDN並找到了Role屬性,但我不知道改變它的正確方法。然後我發現上面貼出的快速修復剪切和粘貼怪物,哈哈。我是新來的wpf。 我試過了代碼,不幸的是,子菜單沒有出現在鼠標懸停中。我會再調查一下。 – 2009-04-18 02:36:46