2013-01-16 77 views
0

在Windows Phone中,有一項名爲ContextMenu的功能,該功能允許爲控件創建彈出菜單。滾動ContextMenu項目

但是,如果菜單項目列表很大,其中一些菜單項不適合屏幕。下面這個簡單的例子顯示了這一點:

在XAML

我們將使用工具包,因此添加

xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit" 

,然後例如:

<Button Content="Button 1" Height="72" HorizontalAlignment="Left" Margin="160,400,0,0" Name="button1" VerticalAlignment="Top" Width="160"> 
     <toolkit:ContextMenuService.ContextMenu> 
      <toolkit:ContextMenu>      
        <toolkit:MenuItem Header="Action A" Name="miActionA1" BorderBrush="Black" BorderThickness="1" Click="nullAction" /> 
        <toolkit:MenuItem Header="Action B" Name="miActionB1" BorderBrush="Black" BorderThickness="1" Click="nullAction" /> 
        <toolkit:MenuItem Header="Action C" Name="miActionC1" BorderBrush="Black" BorderThickness="1" Click="nullAction" /> 
        <toolkit:MenuItem Header="Action D" Name="miActionD1" BorderBrush="Black" BorderThickness="1" Click="nullAction" /> 
        <toolkit:MenuItem Header="Action E" Name="miActionE1" BorderBrush="Black" BorderThickness="1" Click="nullAction" /> 
        <toolkit:MenuItem Header="Action F" Name="miActionF1" BorderBrush="Black" BorderThickness="1" Click="nullAction" />      
      </toolkit:ContextMenu> 
     </toolkit:ContextMenuService.ContextMenu> 
    </Button> 

在nullAction我們'無所事事

private void nullAction(object sender, RoutedEventArgs e) 
     { 

     } 

DesignHeight值是默認WP7頁面的標準配置DesignHeight="768"

正如您所看到的,當您長按「按鈕1」控件時,會顯示菜單,但不會完全顯示。有些項目 不可見。就我而言,最好的決定是讓這個菜單可以滾動。這可以通過使用ScrollViewer來完成。

所以,我們用Scrollviewer和StackPanel來覆蓋菜單項。

<Button Content="Button 1" Height="72" HorizontalAlignment="Left" Margin="160,400,0,0" Name="button1" VerticalAlignment="Top" Width="160"> 
     <toolkit:ContextMenuService.ContextMenu> 
      <toolkit:ContextMenu> 
       <ScrollViewer> 
        <StackPanel> 
        <toolkit:MenuItem Header="Action A" Name="miActionA1" BorderBrush="Black" BorderThickness="1" Click="nullAction" /> 
        <toolkit:MenuItem Header="Action B" Name="miActionB1" BorderBrush="Black" BorderThickness="1" Click="nullAction" /> 
        <toolkit:MenuItem Header="Action C" Name="miActionC1" BorderBrush="Black" BorderThickness="1" Click="nullAction" /> 
        <toolkit:MenuItem Header="Action D" Name="miActionD1" BorderBrush="Black" BorderThickness="1" Click="nullAction" /> 
        <toolkit:MenuItem Header="Action E" Name="miActionE1" BorderBrush="Black" BorderThickness="1" Click="nullAction" /> 
        <toolkit:MenuItem Header="Action F" Name="miActionF1" BorderBrush="Black" BorderThickness="1" Click="nullAction" /> 
        </StackPanel> 
       </ScrollViewer> 
      </toolkit:ContextMenu> 
     </toolkit:ContextMenuService.ContextMenu> 
    </Button> 

成功嗎?不,因爲你可以滾動這個列表,但 不能選擇項目。

我的問題是,如何解決它?

使用多點觸控? (我不太瞭解它)

也許,我需要添加一些屬性Scrolviewer?

還有其他想法嗎?

[已更新]另外,如果添加了scrollviewer,則發現點擊/點擊處理項目會改變行爲。通常,當您點擊該項目時,上下文菜單關閉並執行處理程序方法。使用滾動查看器時,上下文菜單不會關閉,需要再次點擊才能手動關閉它。爲什麼會這樣呢?

回答

0

如果原生ContextMenu不允許這樣做,那麼解決問題的最好方法就是編寫自己的實現。

新的上下文菜單應該顯示在一個彈出窗口中,可以選擇多個項目,並且該項目必須是可滾動的。所以:

public class ScrollableContextMenu 
    { 
     private Popup p; 
     public delegate void TapHandler(object sender, System.Windows.Input.GestureEventArgs e); 
     public event TapHandler ListBoxTap; 

     private ListBox listBox; 

     public ListBox ListBox 
     { 
      get { return listBox; } 
      set { listBox = value; } 
     } 

     /// <summary> 
     /// Create new Context Menu. The items of Context Menu will be taken from given list 
     /// </summary> 
     /// <param name="page"></param> 
     /// <param name="items"></param> 
     public ScrollableContextMenu(PhoneApplicationPage page, List<string> items) 
     { 
      p = new Popup(); 

      // Generate popup properties, i.e. height, width, e.t.c. 

      Canvas canvas = new Canvas(); 

      // Generate canvas main properties 

      p.Child = canvas; 

      Border border = new Border(); 

      // Now create border and its main properties 

      canvas.Children.Add(border); 

      // StackPanel. 
      StackPanel panel = new StackPanel(); 
      panel.Orientation = System.Windows.Controls.Orientation.Vertical; 

      // Create listBox, that we will be scrolling 
      listBox = new ListBox(); 
      // Create listbox main properties 

      // Fill the listbox with items. 
      foreach (string item in items) 
       listBox.Items.Add(new ScrollableContextMenuItem(item)); 
      listBox.Tap += listBoxTap; 
      panel.Children.Add(listBox); 
      border.Child = panel; 
     } 

     public void Show() 
     { 
      // Open the popup. 
      p.IsOpen = true; 
      p.UpdateLayout(); 
     } 

     public void Close() 
     { 
      // Close it 
      p.IsOpen = false; 
      p.UpdateLayout(); 
     } 

     private void listBoxTap(object sender, System.Windows.Input.GestureEventArgs e) 
     { 
      // Invoke hanlder if it exists 
      if (ListBoxTap != null) 
       ListBoxTap(sender, e); 
     } 

ScrollableContextMenuItem是一個用戶控件,它應該看起來像本地的ContextMenuItem。簡而言之,它是一個簡單的TextBox覆蓋Grid/StackPanel。

button.Hold += new EventHandler<System.Windows.Input.GestureEventArgs>(SomeHoldEvent); 



private void SomeHoldEvent(object sender, EventArgs e) 
     { 
      contextMenu = new ScrollableContextMenu(this, definedList); 
      contextMenu.ListBoxTap +=new ScrollableContextMenu.TapHandler(contextMenu_ListBoxTap); 
      contextMenu.Show(); 
     } 

凡定義的列表是頭一個列表:

原生文本菜單添加到XAML文件

<toolkit:ContextMenuService.ContextMenu> 
     <toolkit:ContextMenu> 
       <toolkit:MenuItem Header="..." ... Click="miClickEvent"/> 
       <!-- ... --!> 
     </toolkit:ContextMenu> 
</toolkit:ContextMenuService.ContextMenu> 

相反,ScrollableContextMenu對象應該通過保持事件被稱爲上下文菜單(應該在某處生成)。

在listBoxTap事件:

private void contextMenu_ListBoxTap(object sender, EventArgs e) 
     { 
      int index = contextMenu.ListBox.SelectedIndex; 
      switch (index) 
      { 
       // items index starts with zero 
       case 0: 
        // Call the click event for this one, it should be implemented already, when we've written it for native context menu 
        MiClickEvent(this, EventArgs.Empty); 
        contextMenu.Close(); 
        break; 
       // implement other handlers here 
       default: 
        contextMenu.Close(); 
        break; 
      } 

這是唯一的解決方案,真正幫助了我。希望它能幫助別人。