2012-09-11 44 views
2

我正在WPF中創建一個應用程序。ScrollDown在溢出情況下的ContextMenu

// Create WinForm notify icon 
m_NotifyIcon = new System.Windows.Forms.NotifyIcon(); 
m_NotifyIcon.Icon = Properties.Resources.rocket; 
m_NotifyIcon.Visible = true; 
// Default Balloon title 
m_NotifyIcon.BalloonTipTitle = "Greatest App ever"; 
m_NotifyIcon.ContextMenu = new System.Windows.Forms.ContextMenu(); 

// Append default menu items 
List<MenuItem> itemList = new List<MenuItem>(); 
itemList.Insert(0, new MenuItem("Exit", OnExit_Click)); 
itemList.Insert(0, new MenuItem("-")); 
itemList.Insert(0, new MenuItem("Refresh", RefreshConsoleList)); 
itemList.Insert(0, new MenuItem("Filter: \"" + (String.IsNullOrEmpty(m_Filter) ? "NONE" : m_Filter) + "\"", ChangeFilter_Click)); 
itemList.Insert(0, new MenuItem("-")); 
m_NotifyIcon.ContextMenu.MenuItems.AddRange(itemList.ToArray()); 

的結果看起來是這樣的:

Before Refreshing

我使用 「System.Windows.Forms.NotifyIcon」

代碼看起來像包括了托盤圖標在刷新的情況下,我的應用程序將獲得大量條目,然後將這些條目附加到ContextMenu中,菜單將如下所示:

Overflow of MenuItem

正如你所看到的,有太多的菜單項,並因爲溢出,2個箭頭將顯示(頂部和文本菜單的底部)

現在,如果用戶想退出應用程序,他必須向下滾動,然後單擊退出。 如果列表非常大,可能會惹惱用戶。

爲了避免這種情況,我想顯示的文本菜單已滾動至底部時,它彈出(第一個菜單項是可見的)

但我沒有發現任何事件或控制使用向下滾動編程ContextMenu。

可以嗎?

問候

伊夫Desgraupes


PS:我無法直接發佈,因爲我的名聲的圖像(這是我的第一篇文章),然後發佈超過2個鏈接。

第三爲例是在這裏:

yves.desgraupes.free.fr/shared/ContextMenu_OverflowScroll.png

+0

爲什麼不使用嵌套菜單? –

+0

嵌套菜單是一個好主意,但我真的需要用戶直接訪問列表 –

回答

0

你可以做的是使用WPF實現的NotifyIcon的。

然後你可以有一個WPF菜單,有你如何實現你的菜單中選擇所需的行爲更好地控制。

因此,您可以爲ContextMenu定義模板並獲取對ContextMenu模板中的ScrollViewer的訪問權限,然後在其上調用ScrollToEnd()。

下面是一個示例,顯示如何創建一個WPF上下文菜單,當它啓動時滾動到最後。你可以在你的WPF NotifyIcon中使用它。右鍵單擊按鈕以查看上下文菜單。

注意我已經提供了它作爲一個起點....你可能能夠改善代碼...減少一些重複...但它的工作....例如...當菜單第一次顯示時繞過一個小故障它不滾動到結束我不得不陷入SizeChanged事件。

<Window x:Class="WpfApplication15.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <Style TargetType="{x:Type ContextMenu}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type ContextMenu}"> 
         <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" 
BorderThickness="{TemplateBinding BorderThickness}"> 
          <ScrollViewer x:Name="scrollviewer" 
Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}" 
CanContentScroll="True" > 
           <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="{TemplateBinding Padding}" 
KeyboardNavigation.DirectionalNavigation="Cycle"/> 
          </ScrollViewer> 
         </Border> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </Window.Resources> 
    <Grid> 
     <Button x:Name="mybutton"> 
      <Button.ContextMenu> 
       <ContextMenu> 
        <MenuItem Header="Test1"/> 
       </ContextMenu> 
      </Button.ContextMenu> 
      Test Button 
     </Button>  
    </Grid> 
</Window> 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Windows.Controls.Primitives; 

namespace WpfApplication15 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject 
     { 
      if (depObj != null) 
      { 
       for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) 
       { 
        DependencyObject child = VisualTreeHelper.GetChild(depObj, i); 
        if (child != null && child is T) 
        { 
         return (T)child; 
        } 

        T childItem = FindVisualChild<T>(child); 
        if (childItem != null) return childItem; 
       } 
      } 
      return null; 
     } 

     public MainWindow() 
     { 
      InitializeComponent(); 

      ContextMenu contextmenu = mybutton.ContextMenu; 

      // Add 100 more items 

      for (int i = 2; i <= 100; i++) 
      { 
       MenuItem mi = new MenuItem(); 
       mi.Header = "Item" + i.ToString(); 

       contextmenu.Items.Add(mi); 
      } 

      contextmenu.SizeChanged += new SizeChangedEventHandler(contextmenu_SizeChanged); 
      contextmenu.Loaded += new RoutedEventHandler(contextmenu_Loaded); 

      mybutton.ContextMenuOpening += new ContextMenuEventHandler(mybutton_ContextMenuOpening); 
     } 

     void contextmenu_SizeChanged(object sender, SizeChangedEventArgs e) 
     { 
      ContextMenu contextmenu = mybutton.ContextMenu; 

      ScrollViewer sv = FindVisualChild<ScrollViewer>(contextmenu); 
      if (sv != null) 
      { 
       sv.ScrollToEnd(); 
      } 
     } 

     void contextmenu_Loaded(object sender, RoutedEventArgs e) 
     { 
      ContextMenu contextmenu = mybutton.ContextMenu; 

      ScrollViewer sv = FindVisualChild<ScrollViewer>(contextmenu); 
      if (sv != null) 
      { 
       sv.ScrollToEnd(); 
      } 
     } 

     void mybutton_ContextMenuOpening(object sender, ContextMenuEventArgs e) 
     { 
      ContextMenu contextmenu = mybutton.ContextMenu; 
      ScrollViewer sv = FindVisualChild<ScrollViewer>(contextmenu); 
      if (sv != null) 
      { 
       sv.ScrollToEnd(); 
      } 
     } 
    } 
} 

在一個側面說明....你可能想通過這裏設置MaxHeight ...演示限制文本菜單的高度...。

<Page 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <Grid> 
    <Button> 
    <Button.ContextMenu> 
    <ContextMenu MaxHeight="100"> 
    <MenuItem Header="Test1"/> 
    <MenuItem Header="Test2"/> 
    <MenuItem Header="Test3"/> 
    <MenuItem Header="Test4"/> 
    <MenuItem Header="Test5"/> 
    <MenuItem Header="Test6"/> 
    <MenuItem Header="Test7"/> 
    <MenuItem Header="Test8"/> 
    <MenuItem Header="Test9"/> 
    </ContextMenu> 
    </Button.ContextMenu> 
    Test Button</Button> 
    </Grid> 
</Page> 
+0

你好,感謝你的回答。因此你的觀點是使用NotifyIcon的WPF實現。 我使用了WinForm,因爲在WPF中沒有官方的NotifyIcon實現。 所以沒有辦法滾動來結束WinForm ContextMenu? 如果正確的,我會再次 PS 由於使用WPFContrib的NotifyIcon的:我使用的過去下列WPF的NotifyIcon: [Hardcodet的NotifyIcon類(http://www.hardcodet.net/projects/wpf-notifyicon) 只能創建自定義的氣球提示 –

+0

我無法在WIN32或Windows窗體的「菜單」API中看到任何東西,它們可以讓您滾動到菜單的末尾....也許你可以通過發送按鍵來改變它......但是,將是一個醜陋的解決方案。也許其他人有一些想法。否則WPF方式是可行的。 –

+0

我沒有找到任何東西,並且KeyPress解決方案,滾動不會是即時的(並且真的很難看^^)。所以我使用了WPF實現,現在它工作正常,我很失望WinForm中沒有其他方法。 再次感謝 –

相關問題