3

该问题实际上与此处描述的相同:http: //social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/542b827a-7c8e-4984-9158-9d8479b2d5b1但我对接受的答案不满意在那里,觉得必须有更好的解决方案......

我正在尝试在我的列表视图上实现一个“经典”上下文菜单(不是通过 AppBar,而是通过 PopupMenu),并且效果很好,但前提是我将列表视图设置为“无”选择模式。

上面的链接正确解释了如果 ListView 设置为“无”选择模式以外的 ListViewItem 会“吞下”正确的点击事件。如何覆盖此行为,以便选择列表视图项并且列表视图仍会触发我可以做出反应的 RightTapped 事件?

4

3 回答 3

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>

通过这种简单的方法,即使 SelectionMode 设置为“Single”、“Multiple”或“Extended”,也会调用 MyListView_RightTapped 处理程序。然而,下一个问题是,这个小小的胜利是否会带来一个好的应用程序 UI 设计。我不会在这里尝试回答这个问题......

于 2012-05-08T19:16:55.060 回答
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 中或在选择项目后打开的详细信息页面上显示命令。这可能比试图破解一个从未被设计为支持的东西的解决方法更好。

于 2012-05-08T04:25:32.157 回答
0

我采纳了@Jan Zeman 的想法(顺便说一下;))并对其进行了一些改进。

原始方法的一些问题:

  • 事件处理程序必须设置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.

于 2013-11-23T21:14:12.570 回答