Reputation: 1
I have a custom list-type control (not derived from ListView) with DataTemplate support and various interactive features. To manage the scrollview’s scrolling, I’ve handled the Manipulation Mode for scrollview content. If a user loads a button inside the template and interacts with it while scrolling, the list scrolls but the button's click event also gets triggered upon touch release. If I don’t handle manipulation, the button click is not triggered.
Note : I don't have access to these button inside my source
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Height="100" x:Name="borderControl">
<TextBlock Text="Hello"/>
</Border>
<ScrollViewer x:Name="scrollview" Grid.Row="1">
<StackPanel x:Name="stack">
<Grid Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Click="Button_Click">Click here</Button>
<Border Background="AntiqueWhite" Grid.Column="1"/>
</Grid>
<Grid Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Click="Button_Click">Click here</Button>
<Border Background="Aqua" Grid.Column="1"/>
</Grid>
<Grid Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Click="Button_Click">Click here</Button>
<Border Background="AntiqueWhite" Grid.Column="1"/>
</Grid>
<Grid Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Click="Button_Click">Click here</Button>
<Border Background="Aqua" Grid.Column="1"/>
</Grid>
...
...
....
<Grid Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Click="Button_Click">Click here</Button>
<Border Background="AntiqueWhite" Grid.Column="1"/>
</Grid>
<Grid Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Click="Button_Click">Click here</Button>
<Border Background="Aqua" Grid.Column="1"/>
</Grid>
</StackPanel>
</ScrollViewer>
</Grid>
public sealed partial class MainWindow : Window
{
private double previousOffset;
public MainWindow()
{
this.InitializeComponent();
this.stack.ManipulationMode = ManipulationModes.All;
this.stack.ManipulationDelta += this.Content_ManipulationDelta;
this.stack.ManipulationStarting += this.Content_ManipulationStarting;
}
private void Content_ManipulationStarting(object sender, ManipulationStartingRoutedEventArgs e)
{
this.previousOffset = this.scrollview.VerticalOffset;
}
private void Content_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
if (e.PointerDeviceType == Microsoft.UI.Input.PointerDeviceType.Mouse)
{
return;
}
this.scrollview.ScrollToVerticalOffset(this.previousOffset - e.Cumulative.Translation.Y);
}
bool changed;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (changed)
borderControl.Background = new SolidColorBrush(Colors.Red);
else
borderControl.Background = new SolidColorBrush(Colors.Green);
changed = !changed;
}
}
I have tried the below things to achieve this, but none worked.
- Tried Setting Manipulation mode to system and do my customization on interaction feature using AddHandler for Manipulation event, none of the event triggered.
- Handled Pointer Presses event in Scrollview's content.
- Tried Capturing pointer in Pressed, released and moved.
- IsTapEnabled to false.
- e.handled as false in Manipulation delta with Manipulation Mode: All.
- CancelDirectManipulation for Textblock in pointer pressed.
- Suggested to user - Workaround with scroll check in button click, but not happy with suggestion.
Upvotes: 0
Views: 65
Reputation: 13761
Let me show you an example without manipulation events. At least works with the touch monitor on my laptop.
Shell.xaml
<Page
x:Class="WinUIApp2.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:WinUIApp2"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate
x:Key="ButtonItemTemplate"
x:DataType="x:String">
<Button
Click="Button_Click"
Content="{x:Bind}" />
</DataTemplate>
</Page.Resources>
<ScrollViewer>
<ItemsControl
ItemTemplate="{StaticResource ButtonItemTemplate}"
ItemsSource="{x:Bind Items}" />
</ScrollViewer>
</Page>
Shell.xaml.cs
using Microsoft.UI.Xaml.Controls;
using System.Collections.ObjectModel;
namespace WinUIApp2;
public sealed partial class Shell : Page
{
public Shell()
{
InitializeComponent();
for (int i = 0; i < 100; i++)
{
Items.Add($"Item {i}");
}
}
public ObservableCollection<string> Items { get; } = [];
private void Button_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (sender is not Button button)
{
return;
}
System.Diagnostics.Debug.WriteLine($"{button.Content} clicked.");
}
}
Upvotes: 0