ItemClick 事件在 ListView 上的位置 Windows Phone 8.1
Position of ItemClick event on a ListView Windows Phone 8.1
我有一个 ListView
显示购物车中的产品。 datatemplate
为每个产品定义了一个 increment 和一个 decrement 数量按钮。
如果用户想要点击这些按钮之一,他们有可能点击按钮旁边的按钮,因此会触发 ItemClick
事件。我想在按钮区域禁用 ItemClick
。我想到了获取 ItemClick
事件发生的位置,并确定它是否在我定义的禁用区域中。
可能吗?还有其他想法吗?
建议 1
如果输入靠近按钮,您可能能够收听 DataTemplate
的 ManipulationStarted
根并检查事件处理程序中的 e.Position
。如果距离太近,将 bool
设置为 true,例如 IsCloseToStepperButtons
并在 ItemClick
事件处理程序中检查该布尔值。
尚未对此进行测试,但我认为事件已按所需顺序触发。
建议2
您可以跳过整个 ItemClick
事件并将事件侦听器添加到 DataTemplate
的另一部分。在两个部分之间留一个边距以防止意外点击。
有一种简单的方法可以做到这一点。使用一个元素作为这些 increment/decrement 按钮周围的 "disabled area"。在 ItemClick
处理程序中,说 if (e.OriginalSource == **the element which is the disabled area**) return;
.
这是可行的,因为 ItemClickedEventArgs
是一个 RoutedEventArgs
,它始终包含它的来源元素。参见 https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.itemclickeventargs
为什么要如此艰难?
您可以更改 DataTemplate
,将每个 ListViewItem
分为两部分,"change amount part" 和 "item's info part" :
<ListView ItemClick="OnItemClick">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<!-- This is the item's info part -->
<StackPanel Orientation="Horizontal" Grid.Column="0" >
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Qnty}" />
</StackPanel>
<!-- This is the change amount part -->
<StackPanel Tag="Oops!" Orientation="Horizontal" Grid.Column="1" >
<Button Content="▲" />
<Button Content="▼" />
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
现在您可以尝试以下方法之一来正确处理ItemClick
:
第一个解决方案: 您可以找出引发 ItemClick
事件的 OriginalSource 是什么。如果是 "change amount part",那么用户可能误点了它,事件应该被取消,如果是 "item's info part" 那么应该引发事件:
private void OnItemClick(object sender, ItemClickEventArgs e)
{
var tag = ((FrameworkElement)e.OriginalSource).Tag;
if (tag != null && tag.ToString() == "Oops!")
{
return;
}
//else: do whatever needs to be done on item click
}
第二种方案:
您可以将 ListView
设置为 SelectionMode="None"
和 IsItemClickEnabled="False"
,然后我手动为每个元素添加了 Tapped 处理程序(例如,ItemTapped
用于项目的信息部分,OnIncreaseTapped
和OnDecreaseTapped
按钮):
<ListView ItemClick="OnItemClick" SelectionMode="None" IsItemClickEnabled="False">
...
<!-- This is the item's info part -->
<StackPanel Orientation="Horizontal" Tapped = "OnItemTapped" Grid.Column="0" >
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Qnty}" />
</StackPanel>
<!-- This is the change amount part -->
<StackPanel Tag="Oops!" Orientation="Horizontal" Grid.Column="1" >
<Button Content="▲" Tapped = "OnIncreaseTapped"/>
<Button Content="▼" Tapped = "OnDecreaseTapped"/>
</StackPanel>
</Grid>
第三种解法:
为什么还要让用户点击错误的区域?我宁愿使用这样的 ItemTemplate
来摆脱这个区域:
而不是这个:
我有一个 ListView
显示购物车中的产品。 datatemplate
为每个产品定义了一个 increment 和一个 decrement 数量按钮。
如果用户想要点击这些按钮之一,他们有可能点击按钮旁边的按钮,因此会触发 ItemClick
事件。我想在按钮区域禁用 ItemClick
。我想到了获取 ItemClick
事件发生的位置,并确定它是否在我定义的禁用区域中。
可能吗?还有其他想法吗?
建议 1
如果输入靠近按钮,您可能能够收听 DataTemplate
的 ManipulationStarted
根并检查事件处理程序中的 e.Position
。如果距离太近,将 bool
设置为 true,例如 IsCloseToStepperButtons
并在 ItemClick
事件处理程序中检查该布尔值。
尚未对此进行测试,但我认为事件已按所需顺序触发。
建议2
您可以跳过整个 ItemClick
事件并将事件侦听器添加到 DataTemplate
的另一部分。在两个部分之间留一个边距以防止意外点击。
有一种简单的方法可以做到这一点。使用一个元素作为这些 increment/decrement 按钮周围的 "disabled area"。在 ItemClick
处理程序中,说 if (e.OriginalSource == **the element which is the disabled area**) return;
.
这是可行的,因为 ItemClickedEventArgs
是一个 RoutedEventArgs
,它始终包含它的来源元素。参见 https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.itemclickeventargs
为什么要如此艰难?
您可以更改 DataTemplate
,将每个 ListViewItem
分为两部分,"change amount part" 和 "item's info part" :
<ListView ItemClick="OnItemClick">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<!-- This is the item's info part -->
<StackPanel Orientation="Horizontal" Grid.Column="0" >
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Qnty}" />
</StackPanel>
<!-- This is the change amount part -->
<StackPanel Tag="Oops!" Orientation="Horizontal" Grid.Column="1" >
<Button Content="▲" />
<Button Content="▼" />
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
现在您可以尝试以下方法之一来正确处理ItemClick
:
第一个解决方案: 您可以找出引发 ItemClick
事件的 OriginalSource 是什么。如果是 "change amount part",那么用户可能误点了它,事件应该被取消,如果是 "item's info part" 那么应该引发事件:
private void OnItemClick(object sender, ItemClickEventArgs e)
{
var tag = ((FrameworkElement)e.OriginalSource).Tag;
if (tag != null && tag.ToString() == "Oops!")
{
return;
}
//else: do whatever needs to be done on item click
}
第二种方案:
您可以将 ListView
设置为 SelectionMode="None"
和 IsItemClickEnabled="False"
,然后我手动为每个元素添加了 Tapped 处理程序(例如,ItemTapped
用于项目的信息部分,OnIncreaseTapped
和OnDecreaseTapped
按钮):
<ListView ItemClick="OnItemClick" SelectionMode="None" IsItemClickEnabled="False">
...
<!-- This is the item's info part -->
<StackPanel Orientation="Horizontal" Tapped = "OnItemTapped" Grid.Column="0" >
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Qnty}" />
</StackPanel>
<!-- This is the change amount part -->
<StackPanel Tag="Oops!" Orientation="Horizontal" Grid.Column="1" >
<Button Content="▲" Tapped = "OnIncreaseTapped"/>
<Button Content="▼" Tapped = "OnDecreaseTapped"/>
</StackPanel>
</Grid>
第三种解法:
为什么还要让用户点击错误的区域?我宁愿使用这样的 ItemTemplate
来摆脱这个区域:
而不是这个: