it's done well to scroll by mouse-wheel or scrollbar seed-dragging. but scrolling by mouse-dragging contents on scroll view is not done. How can i implement this action?
<ScrollViewer x:Name="scrollViewer" Grid.Row="1" HorizontalScrollBarVisibility="Auto" CanContentScroll="True">
<Grid x:Name="galleryGrid" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="500"></ColumnDefinition>
<ColumnDefinition Width="500"></ColumnDefinition>
<ColumnDefinition Width="500"></ColumnDefinition>
<ColumnDefinition Width="500"></ColumnDefinition>
<ColumnDefinition Width="500"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Magin="10,10,10,10">Test</Button>
<Button Grid.Column="1" Magin="10,10,10,10">Test</Button>
<Button Grid.Column="2" Magin="10,10,10,10">Test</Button>
<Button Grid.Column="3" Magin="10,10,10,10">Test</Button>
<Button Grid.Column="4" Magin="10,10,10,10">Test</Button>
</Grid>
</ScrollViewer>
I did this class to scroll while keeping the scrollviewer buttons. From the code from user110777, but this works with vertical instead of horizontally, and works well with the viewer (Since I'm now only capturing the content). Plus I'm using MouseLeftButtonDown instead of the preview in order to allow the user to click things like the combobox without causing a drag. (If you want label or Textblock to drag set their IsHitTestVisible=false)
public class ScrollDragger
{
private readonly ScrollViewer _scrollViewer;
private readonly UIElement _content;
private Point _scrollMousePoint;
private double _hOff = 1;
public ScrollDragger(UIElement content, ScrollViewer scrollViewer)
{
_scrollViewer = scrollViewer;
_content = content;
content.MouseLeftButtonDown += scrollViewer_MouseLeftButtonDown;
content.PreviewMouseMove += scrollViewer_PreviewMouseMove;
content.PreviewMouseLeftButtonUp += scrollViewer_PreviewMouseLeftButtonUp;
}
private void scrollViewer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_content.CaptureMouse();
_scrollMousePoint = e.GetPosition(_scrollViewer);
_hOff = _scrollViewer.VerticalOffset;
}
private void scrollViewer_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (_content.IsMouseCaptured)
{
var newOffset = _hOff + (_scrollMousePoint.Y - e.GetPosition(_scrollViewer).Y);
_scrollViewer.ScrollToVerticalOffset(newOffset);
}
}
private void scrollViewer_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_content.ReleaseMouseCapture();
}
}
I found a way of resolving this. It's following...
Point scrollMousePoint = new Point();
double hOff = 1;
private void scrollViewer_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
scrollMousePoint = e.GetPosition(scrollViewer);
hOff = scrollViewer.HorizontalOffset;
scrollViewer.CaptureMouse();
}
private void scrollViewer_PreviewMouseMove(object sender, MouseEventArgs e)
{
if(scrollViewer.IsMouseCaptured)
{
scrollViewer.ScrollToHorizontalOffset(hOff + (scrollMousePoint.X - e.GetPosition(scrollViewer).X));
}
}
private void scrollViewer_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
scrollViewer.ReleaseMouseCapture();
}
private void scrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + e.Delta);
}
thanks!
This is how I did it, XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20px"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="this is not in the scrollviewer" Name="tb"/>
<ScrollViewer Name="sv"
HorizontalScrollBarVisibility="Auto"
Grid.Row="1">
<StackPanel Name="sp" Width="500" Height="500"
MouseMove="sp_MouseMove"
Background="Transparent">
<Ellipse Height="50" Width="50" Fill="Green"/>
</StackPanel>
</ScrollViewer>
</Grid>
C#:
private void sp_MouseMove(object sender, MouseEventArgs e)
{
Point newMousePosition = Mouse.GetPosition((StackPanel)sender);
tb.Text = newMousePosition.X + " | " + newMousePosition.Y;
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
if (newMousePosition.Y < oldMousePosition.Y)
sv.ScrollToVerticalOffset(sv.VerticalOffset + 1);
if (newMousePosition.Y > oldMousePosition.Y)
sv.ScrollToVerticalOffset(sv.VerticalOffset - 1);
if (newMousePosition.X < oldMousePosition.X)
sv.ScrollToHorizontalOffset(sv.HorizontalOffset + 1);
if (newMousePosition.X > oldMousePosition.X)
sv.ScrollToHorizontalOffset(sv.HorizontalOffset - 1);
}
else
{
oldMousePosition = newMousePosition;
}
}
where Point oldMousePosition;
is a member of the window.
UWP variation:
Pointer pointer;
PointerPoint scrollMousePoint ;
double hOff = 1;
private void MainScrollviewer_PointerPressed(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
pointer = e.Pointer;
scrollMousePoint = e.GetCurrentPoint(scrollviewer);
hOff = scrollviewer.HorizontalOffset;
scrollviewer.CapturePointer(pointer);
}
private void MainScrollviewer_PointerReleased(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
scrollviewer.ReleasePointerCaptures();
}
private void MainScrollviewer_PointerMoved(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
if (scrollviewer.PointerCaptures!= null&& scrollviewer.PointerCaptures.Count>0)
{
scrollviewer.ChangeView(hOff + (scrollMousePoint.Position.X - e.GetCurrentPoint(scrollviewer).Position.X),null,null);
}
}
I know that question was for WPF, but this was best result I found searching for UWP solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With