Get scroll event for ScrollViewer on Windows Phone - events

Question:
Get scroll event for ScrollViewer on Windows Phone
I have a scrollviewer like so:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ScrollViewer x:Name="MyScroller">
<StackPanel>
<!-- ... -->
</StackPanel>
</ScrollViewer>
</Grid>
I need the event for when the scrolling occurs for MyScroller:
// MyScroller.Scroll += // <-- "Scroll" event does not exist on ScrollViewer
MyScroller.MouseWheel += MyScroller_MouseWheel; // Does not fire on scroll
MyScroller.ManipulationDelta += MyScroller_ManipulationDelta; // Fires for pinch-zoom only

MouseMove fires when ScrollViewer is scrolled:
public MainPage()
{
InitializeComponent();
MyScroller.MouseMove += MyScroller_MouseMove;
}
void MyScroller_MouseMove(object sender, MouseEventArgs e)
{
throw new NotImplementedException();// This will fire
}
It isn't intuitive, since it is named as a "mouse" event and there is no mouse on the phone. The touch point does move, however, relative to the ScrollViewer container, which is how it can handle scrolling.

It's not that simple, but there's a few scroll detection mechanisms written in this question:
WP7 Auto Grow ListBox upon reaching the last item
Basically take a look at the way OnListVerticalOffsetChanged is called and used.

With Mango, you can watch for the "ScrollStates" visual state to change as described in this sample project.

Related

.net maui CarouselView is not quite compatible with Slider control: CarouselView swipe operation takes over Slider's drag action

.net maui app.
Dragging value element along the slider bar does not work if the the slider put into CarouselView's template like this:
<CarouselView ItemsSource="{Binding Items}">
<CarouselView.ItemTemplate>
<DataTemplate>
<Slider Minimum="0" Maximum="30" WidthRequest="200" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
CarouselView takes over the swipe event for scrolling through the items, and Slider does not get the event (DragStarted is not even called). You can actually click along the slider bar to change its value, so it's not completely frozen, but not how it's supposed to work. Drag & drop is main way user deal with slider control.
Could anyone advise any workaround? I want users to be able scroll through carousel view items also. It's just if they swipe inside the control, event should not handed over to its parent container, if it's possible to do so.
If I add it outside of the corouselview, combine both in Grid and use padding to align slider inside the corouselview, it works as expected, but I need to add lots of additional code, calculate the desirable location and redirect all bindings, which ends up to be an awkward workaround.
At first, I don't suggest you use the slider in the CarouselView. Becasue you want the same behavior has two effects. There is a conflict between them.
But for the android, you can use the custom handler to deal with the swipe event.
Put the Handler class in the /Platform/Android:
public class MySliderHander : SliderHandler
{
protected override void ConnectHandler(SeekBar platformView)
{
base.ConnectHandler(platformView);
platformView.SetOnTouchListener(new SliderListener());
// the listener will make the slider deal with the swip event not the CarouselView.
}
}
Put the SliderListener class in the /Platform/Android
public class SliderListener : Java.Lang.Object, IOnTouchListener
{
public bool OnTouch(global::Android.Views.View v, MotionEvent e)
{
if (e.Action == MotionEventActions.Down || e.Action == MotionEventActions.Move)
{
v.Parent.RequestDisallowInterceptTouchEvent(true);
}
else
{
v.Parent.RequestDisallowInterceptTouchEvent(false);
}
return false;
}
}
And in the MauiProgram.cs:
builder
                  .UseMauiApp<App>()      
                  .ConfigureMauiHandlers(handlers => {
#if ANDROID
                        handlers.AddHandler(typeof(Slider), typeof(YourProjectName.Platforms.Android.MySliderHander));
                  #endif
                  })
In addition, the Slider's height is same as the CarouselView. So you can use a frame to contain the Slider and swipe the CarouselView by swiping the frame.

UWP XAML ScrollViewer scrolling with arrow keys

I have a simple code in XAML and the mainpage:
<Grid>
<ScrollViewer ZoomMode="Enabled" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Image Source="Assets/skyline.jpg" KeyDown="Image_KeyDown">
</Image>
</ScrollViewer>
</Grid>
When I start the programm now, i can scroll with my touchpad, but not with the arrow keys on the keyboard. Why is it like this and how can I change this behaviour? I'm asking this question because I have a much more complex example, where it just works (of course, that example is not only an image). Thank you!
The ScrollViewer responds to unhandled keyboard events that bubble up from its content. In your example you're not seeing keyboarding scroll because neither the Image nor the ScrollViewer are focusable which means there won't be any keyboard events that bubble up to or originate from the ScrollViewer. Image derives from FrameworkElement which doesn't have the concept of focus. ScrollViewer could receive focus. But, by default, it doesn't because its default control style has IsTabStop = "False".
The simple solution here is to set IsTabStop = "True" on the ScrollViewer. Now that its focusable you will start seeing around the ScrollViewer the thick focus rect automatically drawn by the system. You can disable that by also setting the UseSystemFocusVisuals="False".
In markup...
<ScrollViewer x:Name="scrollviewer"
IsTabStop="True" UseSystemFocusVisuals="False"
ZoomMode="Enabled" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Image Source="Assets/skyline.jpg">
</Image>
</ScrollViewer>
Note: This is only necessary because there isn't anything in the content that could receive focus. In more complex scenarios you'll often have something in the ScrollViewer that can be focused (e.g. a 'foo' Button). In those scenarios scrolling happens via keyboarding as you'd expect because some 'foo' has focus.
You could use the ChangeView method of ScrollViewer to scroll in Window.Current.CoreWindow.KeyDown event handler.
Please refer to the following code sample:
<ScrollViewer x:Name="scrollviewer" ZoomMode="Enabled" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Image Source="Assets/skyline.jpg">
</Image>
</ScrollViewer>
public MainPage()
{
this.InitializeComponent();
Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
}
private double horizontalOffset;
private double verticalOffset;
private double step = 5;
private void CoreWindow_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args)
{
Debug.WriteLine("horizontalOffset: "+horizontalOffset+ " verticalOffset: "+verticalOffset);
switch (args.VirtualKey)
{
case Windows.System.VirtualKey.Left: horizontalOffset = horizontalOffset-step<0 ? 0:horizontalOffset - step; scrollviewer.ChangeView(horizontalOffset,verticalOffset,1); break;
case Windows.System.VirtualKey.Right: horizontalOffset = horizontalOffset+step>scrollviewer.ScrollableWidth?scrollviewer.ScrollableWidth: horizontalOffset + step; scrollviewer.ChangeView(horizontalOffset,verticalOffset,1);break;
case Windows.System.VirtualKey.Up: verticalOffset= verticalOffset - step < 0?0:verticalOffset- step; scrollviewer.ChangeView(horizontalOffset,verticalOffset,1);break;
case Windows.System.VirtualKey.Down: verticalOffset = verticalOffset + step > scrollviewer.ScrollableHeight?scrollviewer.ScrollableHeight:verticalOffset+ step; scrollviewer.ChangeView(horizontalOffset,verticalOffset,1);break;
default: break;
}
}

How to automatically call Event in Windows Phone 8

How to automatically raise event in windows phone? For example, I have an element <Image name = "image" .... />. I want when a MainPage is loaded, it will automatically raise tap event on that element
If you want to declare tap event dynamically (loads tap event on page load), You can declare it in following way. Here is your xaml.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Image Name="image1"/>
</Grid>
And in constructor,
public MainPage()
{
InitializeComponent();
image1.Tap += image1_Tap;
}
void image1_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
//Perform your action here
//This method invokes only when you tap on image
}
Else, try the other way.
Loaded += (s, e) =>
{
//Actions that are performed when image is tapped
}
Add above lines in your constructor.
This probably is not a good solution to whatever you are trying to accomplish. It can be done with reflection - How to manually invoke an event? However I'd just extract your Tap event code to method and then call this method in your Loaded event and also Tap even.

Panorama animation is broken when removing ApplicationBar or changing its visibility or opacity

I have 3 panorama items, and I would like only the 1st to have an app bar.
So I started to implement removing the app bar for the other panorama items.
What I did was to handle SelectionChanged event and based on Panorama.SelectedIndex hide the application bar:
this.ApplicationBar.IsVisible = this.Panorama.SelectedIndex == 0;
When swiping to the 2nd item, the usual panorama animation does not work anymore, the transition animation is gone, it's sudden.
Instead of changing IsVisible, I also tried with the same result:
remove app bar this.ApplicationBar = null
set opacity to zero this.ApplicationBar.Opacity = 0
What's interesting is that animation is broken even if changing opacity to let's say 0.5
My feeling is that layout change event in the app bar generate this Panorama broken behavior.
I haven't yet been able to find a solution.
put the whole panorama in а stackpanel
<StackPanel>
<phone:Panorama Title="my application">
<phone:PanoramaItem Header="first item"/>
<phone:PanoramaItem Header="second item" Tap="OnPanoramaItemTap"/>
</phone:Panorama Title="my application">
</StackPanel>
private void OnPanoramaItemTap(object sender, System.Windows.Input.GestureEventArgs e)
{
ApplicationBar.IsVisible = false;
}
It's just an idea, but it's working, i hope it's good for your case

WP7 how to implement a better pivot control?

I'm using pivot control to display a large number of images (about 300). I thought of just using 3 pivot item, and when user swipes, change either pivot item or update item source. But I don't know how to do this efficiently ?
Or is there a way of using gesture and stimulating swipe effect as the pivot does ? Something like transition ?
You can use normal Image Control with gesture Manipulation events to swipe left to right and right to left for previous/next photos.
Please find the code below.
XAML Code
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Margin="0">
<Image Margin="0" x:Name="ImagePanel" Source="{Binding SelectedPhoto.PhotoURL}" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
C# code
public SlideShow()
{
// Tag ManipulationCompleted event for the current page in the constructor.
ManipulationCompleted += new EventHandler<ManipulationCompletedEventArgs>(SlideShow_ManipulationCompleted);
}
// ManipulationCompleted event. Update the Previous/next photo based on the swipe direction.
void SlideShow_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
var manipEndPoint = e.TotalManipulation.Translation;
const int threshold = 100;
if ((manipEndPoint.X > _manipStartPoint.X) && ((manipEndPoint.X - _manipStartPoint.X) > threshold))
{
LoadPreviousPhoto();
}
else if ((manipEndPoint.X < _manipStartPoint.X) && ((_manipStartPoint.X - manipEndPoint.X) > threshold))
{
LoadNextPhoto();
}
}
Let me know if you need any more help.
Thanks,
Kamal.

Resources