2012-05-07 54 views
3

問題與此處所述的幾乎相同:http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/542b827a-7c8e-4984-9158-9d8479b2d5b1但我不滿意接受的答案,並認爲必須有更好的解決方案。 ..如果ListView處於「None」選擇模式以外,則RightTapped不會觸發Metro ListViewItem

我想在我的列表視圖(不是通過AppBar,但通過PopupMenu)實現'clasic'上下文菜單,但工作正常,但只有當我將列表視圖設置爲「None」SelectionMode。

上面的鏈接正確地解釋瞭如果ListView設置爲「無」選擇模式以外,ListViewItem'吞下'右擊事件。我如何覆蓋這種行爲,以便列表視圖項被選中,並且列表視圖仍會觸發RightTapped事件,我可以對此做出反應?

回答

7

我相信我通過繼承ListView和ListViewItem類來解決問題。

public class MyListView : ListView 
{ 
    protected override DependencyObject GetContainerForItemOverride() 
    { 
     return new MyListViewItem(); 
    } 
} 

public class MyListViewItem : ListViewItem 
{ 
    protected override void OnRightTapped(Windows.UI.Xaml.Input.RightTappedRoutedEventArgs e) 
    { 
     base.OnRightTapped(e); 
     e.Handled = false; // Stop 'swallowing' the event 
    } 
} 

<CustomControls:MyListView 
    x:Name="MyListView" 
    ... 
    SelectionMode="Single" 
    RightTapped="MyListView_RightTapped"> 
</CustomControls:MyListView> 

通過這個簡單的方法MyListView_RightTapped即使selectionMode是設置爲「單」處理程序被調用,「多」或「擴展」。然而,下一個問題是這個小勝利是否會導致應用程序UI的良好設計。我不會試圖在這裏回答這個問題...

1

您可以使用GridViewItem上的PointerPressed/PointerReleased事件來獲得您從RightTapped或ManipulationCompleted獲得的相同效果。

<ListView 
     Margin="120,80,0,0" 
     SelectionMode="Multiple"> 
     <ListView.ItemContainerStyle> 
      <Style 
       TargetType="ListViewItem"> 
       <Setter 
        Property="Width" 
        Value="100" /> 
       <Setter 
        Property="Height" 
        Value="100" /> 
      </Style> 
     </ListView.ItemContainerStyle> 
     <ListViewItem 
      RightTapped="ListViewItem_RightTapped_1" 
      PointerPressed="ListViewItem_PointerPressed_1" 
      PointerReleased="ListViewItem_PointerReleased_1" 
      ManipulationStarted="ListViewItem_ManipulationStarted_1"> 
      <Rectangle 
       Height="80" 
       Width="80" 
       Fill="Red" /> 
     </ListViewItem> 
    </ListView> 

private void ListViewItem_RightTapped_1(object sender, RightTappedRoutedEventArgs e) 
    { 
     Debug.WriteLine("Tap"); 
    } 

    private void ListViewItem_PointerPressed_1(object sender, PointerEventArgs e) 
    { 
     Debug.WriteLine("Press"); 
    } 

    private void ListViewItem_ManipulationStarted_1(object sender, ManipulationStartedRoutedEventArgs e) 
    { 
     Debug.WriteLine("Manipulating"); 
    } 

    private void ListViewItem_PointerReleased_1(object sender, PointerEventArgs e) 
    { 
     Debug.WriteLine("Release"); 
    } 
} 

輸出:

新聞 發佈 新聞 發佈

*編輯

對不起,我必須以某種方式,這些事件與觸摸和鼠標的工作方式不同錯過了。我認爲你得到的答案可能是最好的。否則 - 你需要實現你自己的ListView版本。你可以嘗試向他們施壓,希望能夠在未來版本中獲得更好的解決方案,但我不希望在那裏有太多的希望。從我記得的地方 - ContextMenus不是非常地鐵,有更好的UX解決方案比右鍵菜單。您可以在AppBar中或在選擇項目後打開的詳細信息頁面中顯示命令。這可能比試圖破解某種從未被設計爲支持的解決方法更好。

+0

非常感謝你的回答,菲利普。其實我讀了Metro UI的規格,我知道PopupMenu的非地鐵實體。在決定使用PopupMenu來支持AppBar之前,我花了相當長的時間來處理我想要討論的特定場景。我甚至做出了一個正反兩面的表格來使這個決定得到很好的論證;)但是我會再次重新考慮它,也許真的會去AppBar。無論如何,通過我原來的問題,我也許發現自己也是一個解決方案。我會在這裏發佈,並有興趣聽取您的意見... –

0

我拿@Jan Zeman的想法(upvoted,順便;))並改進了一下。

與原辦法中的幾個問題:

  • 事件處理程序必須設置e.Handled = true,否則事件會冒泡,直到Page本身處理正確的敲擊事件 - 並因此打開應用酒吧。
  • 如果沒有人聽這個活動,那麼活動將總是冒泡並達到Page
  • 當物品周圍的白色空間上的清單項目上出現右擊時,將觸發事件處理程序。

這種方法解決上述問題:

public class MyListView : ListView 
{ 
    public event RightTappedEventHandler ItemRightTapped; 

    protected override DependencyObject GetContainerForItemOverride() 
    { 
     var item = new MyListViewItem(); 
     item.RightTapped += OnItemRightTapped; 
     return item; 
    } 

    protected virtual void OnItemRightTapped(object sender, RightTappedRoutedEventArgs args) 
    { 
     if (ItemRightTapped != null) 
      ItemRightTapped(sender, args); 
     args.Handled = true; 
    } 
} 

public class MyListViewItem : ListViewItem 
{ 
    protected override void OnRightTapped(RightTappedRoutedEventArgs e) 
    { 
     base.OnRightTapped(e); 

     // Stop 'swallowing' the event 
     e.Handled = false; 
    } 
} 

現在,您可以訂閱ItemRightTapped事件相反,當且僅當一個項目是正確的挖掘,這將被觸發。

該項目將事件標記爲未處理,該列表將讓您處理事件,然後將其標記爲已處理 - 防止它冒泡並擊中Page

相關問題