RightTapped does not start in the Metro ListViewItem if the ListView is in contrast to the None selection mode

The question is almost the same as described here: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/542b827a-7c8e-4984-9158-9d8479b2d5b1 , but I donโ€™t like the accepted answer and I feel what to be the best solution ...

I am trying to implement the "clasic" context menu in my list view (not via AppBar, but via PopupMenu), and this works fine, however, only if I set the list view to "None" SelectionMode.

The correct link correctly explains that the ListViewItem "swallows" the correct event if the ListView is set to something other than "No". How can I override this behavior so that the list items of the list are selected AND viewing the list still raises the RightTapped event that I can respond to?

+3
source share
3 answers

I believe that I solved the problem by subclassing the ListView and ListViewItem classes.

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> 

This simple approach is invoked by the MyListView_RightTapped handler, even if the SelectionMode parameter is set to Single, Multiple, or Extended. The next question, however, is whether this small victory leads to a good UI design for the application. I will not try to answer this question here ...

+7
source

You can use the PointerPressed / PointerReleased events in the GridViewItem to get the same effect you could get in RightTapped or 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"); } } 

Output:

Press Release Press Release

* EDIT

Sorry, I must have missed something, that these events work differently with touch and mouse. I think the answers received may be the best you get. Otherwise, you will need to implement your own version of ListView. You can try to put pressure on them with the hope of a better solution in a future release, but I would not expect much. From what I remember, ContextMenus is not a great metro, and there are better UX solutions than right-click menus. You can display commands in the AppBar or on the details page that opens after selecting an item. This may work better than trying to crack a workaround for something that was never intended to be supported.

+1
source

I took @Jan Zeman's idea (compared to this) and improved it a bit.

A few problems with the original approach:

  • The event handler will have to set e.Handled = true , otherwise the event will bubble until Page itself processes the direct tap event - and, therefore, opens the application panel.
  • If no one is listening to this event, the event will always bubble and reach Page .
  • An event handler will be triggered when the right-hand item touches an OR list item on a space surrounding the items.

This approach solves the problems above:

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

Now you can subscribe to the ItemRightTapped event instead, which will fire if and only if the item is correctly clicked.

The element will mark the event as unprocessed, the list will allow you to process the event, and then mark it as processed - to prevent it from bubbling and press Page .

0
source

Source: https://habr.com/ru/post/1437550/


All Articles