WPF C# Make ScrollBar Clickable Only - c#

I am creating an application which currently lets users scroll to zoom into an image. Currently, if I try to use a scrollview to allow users to scroll down the page, it breaks this feature. Is there any way for me to implement a scrollbar that does not access the scroll wheel? What I am looking for is a way to only allow users to access the scrollbar by clicking it, not by using the scrollwheel.

Set the MouseWheel event on your image and set e.Handled = true at the end.
Contrived example -
XAML:
<Grid>
<ScrollViewer>
<Canvas Width="1000" Height="1000" Background="PeachPuff" MouseWheel="Canvas_MouseWheel" />
</ScrollViewer>
</Grid>
Code:
private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
(sender as Canvas).Background = Brushes.Blue;
e.Handled = true;
}

Related

UWP XAML ScrollViewer how to show visual indicator of scrollable content

Is there a way to visually indicate that there is scrollable content below the visible area of a <ScrollViewer>?
I see this effect in applications like Microsoft Teams. A shadow appears at the bottom of the scrollable area to indicate that more content is present.
None of the properties of <ScrollViewer> seem to be a clear match. But I'm hoping I can avoid having to programmatically show/hide an element below the <ScrollViewer> based on the scroll position.
I have to say that currently there is no built-in API in ScrollViewer that could directly show a shadow there if the content is not ended.
You might still need to check it programmatically by handling the ViewChanged event of the ScrollViewer and add a custom element.
You could use the following code to check if the ScrollViewer reaches the end:
<Grid>
<ScrollViewer Name="MyScrollViewer" ViewChanged="MyScrollViewer_ViewChanged">
<Rectangle
x:Name="MyRectangle"
Width="3000"
Height="3000"
Fill="Blue"
Margin="20" />
</ScrollViewer>
</Grid>
Code behind:
private void MyScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
var verticalOffset = MyScrollViewer.VerticalOffset;
var maxVerticalOffset = MyScrollViewer.ScrollableHeight;
if (maxVerticalOffset < 0 || verticalOffset == maxVerticalOffset)
{
// content reaches the end
MyRectangle.Fill = new SolidColorBrush(Colors.Red);
}
else
{
// content does not reach the end
MyRectangle.Fill = new SolidColorBrush(Colors.Blue);
}
}

How to disable swipe navigation of flipview on touch in c# in windows store apps

I have developed an app in which I have more than one page in flipview.
now I want to stop the swipe navigation on touch only. i have used Isenabled property but
This will disable the content of the flipview as well, I just wanted to disable its navigation but allow the user to interact with its content because I have need to drag and drop and also zoom-in and zoom-out with its content.
please help me in solving the problem.
You can try this method by setting the ManipulationMode as TranslateX and put the code below inside your FlipView:
xaml:
<FlipView Width="300" Height="300" Name="MyFlipView">
<FlipViewItem ManipulationMode="TranslateX" ManipulationDelta="FlipViewItem_ManipulationDelta">
<Image Source="Assets/1.jpg" ></Image>
</FlipViewItem>
<FlipViewItem ManipulationMode="TranslateX" ManipulationDelta="FlipViewItem_ManipulationDelta">
<Image Source="Assets/2.jpg" ></Image>
</FlipViewItem>
</FlipView>
code behind:
private void FlipViewItem_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
if (e.Delta.Translation.X != 0)
{
e.Handled = true;
}
}
In order to disable the swipe navigation of FlipView on touch without affecting the FlipViewItem content, please override the ControlTemplate and change ManipulationMode as None in ItemsPresenter and put the code below inside your FlipView:
<FlipView.Template>
<ControlTemplate>
<ItemsPresenter ManipulationMode="None"></ItemsPresenter>
</ControlTemplate>
</FlipView.Template>
I have tested it and it works OK.

Kinect 2 onHover click

I am working on a Kinect application for WPF (Kinect 2). I am using the KinectRegion to trigger some buttons, but i want to trigger the buttons on hover and not on click. what is the best way to achieve this? I have tried with MouseEnter and MouseLeave with no luck. My goal is that when the user hovers on a button an animation is played and then after 2 seconds the buttons is clicked. I would appreciate any help!
<k:KinectRegion x:Name="kinectRegion" >
<Grid Background="White" Name="gridTest">
<k:KinectUserViewer Height="400" Width="300" HorizontalAlignment="Center" VerticalAlignment="Top" DefaultUserColor="#FFF93636" EngagedUserColor="#FF395913" />
<Button Name="buttonStartSpel" Width="400" Height="200" Margin="0,800,0,0" VerticalAlignment="Top" HorizontalAlignment="Center" Content="Start het spel" Style="{StaticResource KinectCustomButton}" MouseEnter="buttonStartSpel_MouseEnter" MouseLeave="buttonStartSpel_MouseLeave"></Button>
</Grid>
</k:KinectRegion>
UPDATE -
Looking for multiple ways to solve this i came up with this solution:
We executed the code on window load.
void KinectPointerPointSample_Loaded(object sender, RoutedEventArgs e)
{
// Listen to Kinect pointer events
KinectCoreWindow kinectCoreWindow = KinectCoreWindow.GetForCurrentThread();
kinectCoreWindow.PointerMoved += kinectCoreWindow_PointerMoved;
}
private void kinectCoreWindow_PointerMoved(object sender, KinectPointerEventArgs args)
{
KinectPointerPoint kinectPointerPoint = args.CurrentPoint;
bool isEngaged = kinectPointerPoint.Properties.IsEngaged;
if (isEngaged)
{
System.Drawing.Point mousePt = new System.Drawing.Point((int)(kinectPointerPoint.Position.X * kinectRegion.ActualWidth - 80), (int)(kinectPointerPoint.Position.Y * kinectRegion.ActualHeight));
System.Windows.Forms.Cursor.Position = mousePt;
}
}
Noticed that the mouse pointer does not have the exact same position of the handpointer, i have tested that with negative results. Thats why i placed the mouse pointer slightly left to the handpointer (80 pixs to be exact). You can play around depending on your project. Finally we hide the mouse pointer with the following code:
this.Cursor = Cursors.None;
Now we can use the OnMouseEnter and OnMouseLeave events...I hope this helps anyone having this problem.

Ways to open MahApps Flyout

I've been working with MahApps and wanted to add a Flyout window. I assumed incorrectly that the logic was included with the control to detect when it should be opened closed.
What are some ways the community have been accomplishing this?
Currently I have added a rectangle to the grid on the far edge that uses mouse enter events to display the flyout and then the built in close arrow button.
What other neat ways are people doing this?
<controls:MetroWindow.Flyouts>
<controls:FlyoutsControl Name="FlyoutControlSettings" Background="Beige">
<controls:Flyout x:Name="yourMahAppFlyout" Header="Flyout" Theme="Accent" Position="Left" Width="600" IsOpen="False" BorderBrush="Black" BorderThickness="3,0,3,3">
<TextBlock FontSize="24">Hello World</TextBlock>
</controls:Flyout>
</controls:FlyoutsControl>
</controls:MetroWindow.Flyouts>
And then then code would look like this
private void ToggleFlyoutSetting(object sender, RoutedEventArgs e)
{
yourMahAppFlyout.IsOpen = !yourMahAppFlyout.IsOpen;
}

ScrollViewer mouse wheel not scrolling

I am currently working on my first WPF project and trying to make a ListView scrollable.
At first I thought this could be easily done by simply limiting the ListView's width and height and thus forcing a scrollbar to appear automatically whenever the content exceeds its space. This seemed fine at first but due to the handled PreviewMouseDown event (which enables dragging the list's items) it doesn't work after selecting an item.
Second attempt (using ScrollViewer)
<ScrollViewer>
<ListView ItemsSource="{Binding FileViewModels}"
PreviewMouseDown="ListView_MouseMove"
Height="450" Width="200"/>
</ScrollViewer>
Of course, this resulted in a second scrollbar whenever the list's content became larger than its max height. And dragging the bar still didn't work after selecting an item.
Third (quite foolish) attempt (disabling scrollbar duplicate)
<ScrollViewer>
<ListView ItemsSource="{Binding FileViewModels}"
PreviewMouseDown="ListView_MouseMove"
Height="450" Width="200"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
</ScrollViewer>
This removed the scrollbar duplicate and enabled scrolling via mouse wheel but disabled the scrollbar, so you couldn't move by clicking and dragging it.
Fourth attempt (constant size of the ScrollViewer)
<ScrollViewer Height="450" Width="200">
<ListView ItemsSource="{Binding FileViewModels}"
PreviewMouseDown="ListView_MouseMove"/>
</ScrollViewer>
Removed the width/height constraint from the ListView and moved it to the ScrollViewer. This enables the scrollbar and removes the duplicate. Unfortunately the mouse wheel doesn't work anymore (dragging the scroll bar works fine).
Could somebody please explain to me why the mouse wheel doesn't work anymore and how to fix this?
Edit
Maybe I should go back to my first solution.
Obviously, the ListView's template already contains a ScrollViewer. The remaining problem would then be that I cannot drag the scrollbar after selecting an item because of the handled PreviewMouseDown event (scrolling via MouseWheel still works in that case). Should I handle the dragging of items differently (it worked fine for me, before wanting to add a scrollbar)? Or is there a way to detect if the cursor is above the scrollbar (so I could then deselect the item which enables scrolling)?
Or are there any other suggestions?
This may help you..
private void ListViewScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
ScrollViewer scv = (ScrollViewer)sender;
scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
e.Handled = true;
}
This would probably be the most comfortable solution:
<ListView.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</ControlTemplate>
</ListView.Template>
For me this worked:
<ListView.Template>
<ControlTemplate>
<!-- Empty template to allow ScrollViewer to capture mouse scroll -->
<ItemsPresenter />
</ControlTemplate>
</ListView.Template>
instead of this:
<ListView.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</ControlTemplate>
</ListView.Template>
<ScrollViewer Background="Transparent">
If Background is null, the mouse wheel will not work on ScrollViewer. You can set the Background to Transparent or some other value.
In my case this helped:
<ScrollViewer ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Auto" >
<DataGrid x:Name="dataGrid" SelectionMode="Single" ItemsSource="{Binding}" SelectedValuePath="{Binding Item}" AutoGenerateColumns="True">
</DataGrid>
</ScrollViewer>
The design was disabling VerticalScrollBarVisibility attribute in outer scope , i.e. in ScrollViewer.
I want to add some comment to the solution Rocky provided. It worked fine for me, but later I needed to use it in a different window to scroll Grid. I faced a problem: the ScrollViewer did not scroll to the bottom end. The reason was because of attempts to set the invalid VerticalOffset value. The code below works fine for me (just need to change PreviewMouseWheel handler:
private void UIElement_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
ScrollViewer scroll = (ScrollViewer)sender;
if (e.Delta < 0)
{
if (scroll.VerticalOffset - e.Delta <= scroll.ExtentHeight - scroll.ViewportHeight)
{
scroll.ScrollToVerticalOffset(scroll.VerticalOffset - e.Delta);
}
else
{
scroll.ScrollToBottom();
}
}
else
{
if (scroll.VerticalOffset + e.Delta > 0)
{
scroll.ScrollToVerticalOffset(scroll.VerticalOffset - e.Delta);
}
else
{
scroll.ScrollToTop();
}
}
e.Handled = true;
}

Categories

Resources