问题与此处描述的几乎相同:http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/542b827a-7c8e-4984-9158-9d8479b2d5b1但我对那里接受的答案感到不满意,并认为必须有更好的解决方案......
我正在尝试在列表视图上实现'clasic'上下文菜单(不是通过AppBar,而是通过PopupMenu)并且工作正常,但是只有将列表视图设置为“无”SelectionMode时才会生效。
上面的链接正确地解释了如果ListView设置为“无”选择模式以外的ListViewItem'吞下'右侧轻敲事件。如何覆盖此行为,以便列表视图项被选中,列表视图仍然会触发我可以响应的RightTapped事件?
答案 0 :(得分: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的良好设计。我不会试图在这里回答这个问题......
答案 1 :(得分: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中或在选择项目后打开的详细信息页面上显示命令。这可能比尝试破解从未设计为支持的东西的解决方法更好。
答案 2 :(得分: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
。