I want to implement an UI for finger controling, in WPF C# .Net framework, VS2019.
ManipulationDelta event is added on a Rectangle and it supposed to work continiously. But when I test it, it triggered only once at the moment I tapped(touch down). This event should be triggered continuously while my finger pressing.
Target: Show the position of pointer within the rectangle area.
XAML:
<Window x:Class="WpfApp5.MainWindow"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp5"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid Margin="0,0,-322,-112">
<Rectangle
ManipulationDelta="Rectangle_ManipulationDelta"
TouchMove="Rectangle_TouchMove"
Fill="#FFF4F4F5"
HorizontalAlignment="Left"
Height="274" Margin="162,70,0,0"
Stroke="Black"
VerticalAlignment="Top"
Width="582" IsManipulationEnabled="True"/>
<TextBlock
x:Name="textBlock"
HorizontalAlignment="Left"
TextWrapping="Wrap"
VerticalAlignment="Top"
Margin="31,26,0,0"><Run Text="TextBlock"/></TextBlock>
</Grid>
Here is the event to print the postion of finger:
C#:
namespace WpfApp5{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Rectangle_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
}
private void Rectangle_TouchMove(object sender, TouchEventArgs e)
{
textBlock.Text = "Manipulation Touch: " + Mouse.GetPosition(Application.Current.MainWindow).ToString();
}
}
}
UI tested on Windows10 Simulator v16 and Surface Pro
Holding right-clicking is disabled
A test video is here to describe the issue with subtitle
Test Video
After testing, the event likes TouchMove, MouseMove, ManipulationDelta will be fired only if the cursor "get into" the border of element. I want to trigger this event within target area. Or should I use another event to achieve this?
Any suggestion is appreciated! Thank you.
I found that I use worng event, I should use TouchMove instead of ManipulationDelta(manipulation means manipulation for translation, zoom, etc, it's not necessary in this case).
And the flag should be set to false:
IsManipulationEnabled="false"
It working now! And thanks for who paticipating this discussion.
Related
I am creating an application in WPF that relies on multi-touch and, although I can receive multiple touch points, the WPF controls do not behave as expected when multiple touches occur at the same time.
I created a simple test WPF application using buttons for visualization to ensure it wasn't anything in my project causing the issue.
The XAML:
<Window x:Class="TouchSample3.MainWindow"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TouchSample3"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid TouchDown="Grid_TouchDown">
<Button x:Name="button1" Content="Button" HorizontalAlignment="Left" Margin="108,86,0,0" VerticalAlignment="Top" Width="70" Height="70" Click="button1_Click" TouchDown="button1_TouchDown"/>
<Button x:Name="button2" Content="Button" HorizontalAlignment="Left" Margin="322,86,0,0" VerticalAlignment="Top" Width="70" Height="70" Click="button2_Click" TouchDown="button2_TouchDown"/>
</Grid>
</Window>
and here is my MainWindow:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("Button 1 clicked.");
}
private void button2_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("Button 2 clicked.");
}
// TouchDown events
private void button1_TouchDown(object sender, TouchEventArgs e)
{
Console.WriteLine("Button 1 Touch Down.");
}
private void button2_TouchDown(object sender, TouchEventArgs e)
{
Console.WriteLine("Button 2 Touch Down.");
}
}
When I perform a single touch on either button it fires as expected, the TouchDown event, and Click event along with the button animation occur.
However, when I attempt to do two touches simultaneously (one finger held down, another one pressing), the TouchDown events get fired but the the Click events and the button animations do not happen.
It clearly registers the touch points but I don't understand why it doesn't perform actions/events to the WPF controls when touches happen simultaneously.
Any help or direction would be appreciated.
I think thats because the old version of Click event is not prepared well for a multi-touch wpf application. It is primary classified as a mouse event, since the TouchDown is touch event primary so it support the multi-touch feature.
I have custom window with WindowState=WindowState.Maximized with border and thumb inside in the border, it seems that when the WindowState=WindowState.Maximized I cannot drag and move the custom window to different screen.
Xaml:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525"
WindowStyle="None">
<Border Name="headerBorder"
Width="Auto"
Height="50"
VerticalAlignment="Top"
CornerRadius="5,5,0,0"
DockPanel.Dock="Top"
Background="Red"
BorderThickness="1,1,1,1"
BorderBrush="Yellow">
<Grid x:Name="PART_Title">
<Thumb x:Name="headerThumb"
Opacity="0"
Background="{x:Null}"
Foreground="{x:Null}"
DragDelta="headerThumb_DragDelta"/>
</Grid>
</Border>
</Window>
C#:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
WindowState = System.Windows.WindowState.Maximized;
}
private void headerThumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
Left = Left + e.HorizontalChange;
Top = Top + e.VerticalChange;
}
}
I've also overridden MouseLeftButtonDown method and using DragMove() inside but without success. I've also tried to subscribe to thumb's MouseLeftButtonDown and write there DragMove() but without success.
By default, maximized windows cannot be moved, thus Left and Top have no effect. One option would be to register to the Thumb.DragStarted event and check if the window is maximized. If yes, you can set WindowState.Normal and successively update the Left and Top properties.
In code, this would look somewhat like this:
private void Thumb_OnDragStarted(object sender, DragStartedEventArgs e)
{
// If the window is not maximized, do nothing
if (WindowState != WindowState.Maximized)
return;
// Set window state to normal
WindowState = WindowState.Normal;
// Here you have to determine the initial Left and Top values
// for the window that has WindowState normal
// I would use something like the native 'GetCursorPos' (in user32.dll)
// function to get the absolute mouse point on all screens
var point = new Win32Point();
GetCursorPos(ref point);
Left = point - certainXValue;
Top = point - certainYValue;
}
You can learn more about GetCursorPos here.
However, I would strongly advise you to use the WindowChrome class that comes with .NET 4.5 and that was also suggested by Max in the comments. You just have to use the following code and you have the functionality you're asking for:
<Window x:Class="ThumbMaximizedWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350"
Width="525"
WindowStyle="None"
WindowState="Maximized">
<WindowChrome.WindowChrome>
<WindowChrome />
</WindowChrome.WindowChrome>
</Window>
I have done carousels in web development, but animating them in WPF through XAML or C# is new to me. There are examples on the web, but they either are outdated or not what I am looking for. Even when I play around with source code of other projects, it's not what I hope for.
I want to have images sliding left-to-right (horizontally) automatically. The user cannot interact with the images to stop the sliding. While I can do this manually in a ScrollViewer, the process is manual...
ScrollViewer doesn't have any dependencies for animation. I tried using this to see if it is possible, but the application would always crash. Example I used..
Another attempt I've tried is storing images in a StackPanel, making sure the StackPanel is the width of one of my images, then having DispatcherTimer set to animate the TranslateTransform's X property. But...that didn't go anywhere.
Using a ScrollViewer or StackPanel is not important at all. I just want to have a carousel-like effect automatically transitioning through images. Sort of like THIS
I'm currently using Visual Studio 2012 and 2013, if it helps.
Is there a way to do this?
I' ve prepared exemplary carousel in wpf. You might want to use the code in form of UserControl for instance. As you proposed I prepared carousel with use of StackPanel. Code of my form looks as follows:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Storyboard x:Key="CarouselStoryboard">
<DoubleAnimation
Storyboard.TargetName="CarouselTransform"
Storyboard.TargetProperty="X"/>
</Storyboard>
</Window.Resources>
<Canvas>
<StackPanel Name="Carousel" Orientation="Horizontal">
<StackPanel.RenderTransform>
<TranslateTransform x:Name="CarouselTransform" />
</StackPanel.RenderTransform>
<Button Height="350" Width="525" Content="Page1"/>
<Button Height="350" Width="525" Content="Page2"/>
<Button Height="350" Width="525" Content="Page3"/>
</StackPanel>
<Button Click="Left_Click" Content="Left" HorizontalAlignment="Left" Margin="10,164,0,0" VerticalAlignment="Top" Width="45">
</Button>
<Button Click="Right_Click" Content="Right" HorizontalAlignment="Left" Margin="448,170,0,0" VerticalAlignment="Top" Width="45"/>
</Canvas>
</Window>
The Storyboard element within WindowResources defines animation to be performed. It will change X property of TranslationTransform applied to StackPanel "Carousel" - this will result in animated movement of that panel. 3 buttons within the panel simulates 3 panels of the carousel. At the bottom there are 2 buttons - one for moving left and second for moving right. There are callback methods bounded to them. Code behind of the form looks like that:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private int currentElement = 0;
private void Left_Click(object sender, RoutedEventArgs e)
{
if(currentElement < 2)
{
currentElement++;
AnimateCarousel();
}
}
private void Right_Click(object sender, RoutedEventArgs e)
{
if (currentElement > 0)
{
currentElement--;
AnimateCarousel();
}
}
private void AnimateCarousel()
{
Storyboard storyboard = (this.Resources["CarouselStoryboard"] as Storyboard);
DoubleAnimation animation = storyboard.Children.First() as DoubleAnimation;
animation.To = -this.Width * currentElement;
storyboard.Begin();
}
}
currentElement field holds information which panel is currently being displayed to the user. Method AnimateCarousel actualy starts the animation. It refers to Storyboard defined in Resources and sets its DoubleAnimation To property to the value to which Carousel panel should be moved. Then by calling Begin method on storyboard it performs animation.
I made a usercontrol in WPF with an image in it. I declared a MouseDown event for this image:
<Image x:Name="imgState" Height="300" Width="300" MouseDown="imgState_MouseDown" OpacityMask="#00000000" />
I placed this usercontrol on my application form, but the event isn't fireing. I'm pretty new to WPF and I read about RoutedEvents but I don't really understand it. I would be happy if someone could help and explain this to me!
Update
Changing to PreviewMouseDown didn't fire the event too. I tried setting the background to transparent and even tried with a blank 300x300 image. The grid workaround doesn't fire the event too. Here is how my code behind looks like:
private void imgState_MouseDown(object sender, MouseButtonEventArgs e)
{
//Some code here
}
Update 2
Here is my whole XAML file:
<UserControl x:Class="TicTacToe.controls.SingleField"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Image x:Name="imgState" MouseDown="imgState_MouseDown" Height="300" Width="300" Stretch="None" OpacityMask="#00000000"/>
</Grid>
</UserControl>
I removed the source again because I set one from code behind at runtime and adding a transparent/clear image didn't helped.
You probably want PreviewMouseUp instead of MouseDown event
<Image x:Name="imgState" Height="300" Width="300"
PreviewMouseUp="ImgState_OnPreviewMouseUp"
PreviewMouseDown="ImgState_OnPreviewMouseDown"/>
Either of the two, you can capture the event from there.
If the answer above does not help:
Not a very nice solution but does work so many times:
Wrap your image with a grid on which you will have your event...
<Grid MouseDown="imgState_MouseDown">
<Image/>
</Grid>
Okay I solved the problem myself.
The problem was the setting OpacityMask="#00000000" that prevented the image from appearing so there were, as #lll said, nothing to hit. I don't know when the setting was set, but I think it happened automatically while expanding the Representation tab.
Thanks for helping me!
I am very new to XAML and WPF.I have a problem.
I have two files. first.xaml and second.Xaml. There is a button in first.xaml, on click of which it should navigate to second.xaml.How do i achieve this.
This is one way of organising the code:
Your second.xaml should contain your window definiton e.g.:
<Window x:Class="MediaCheckerWPF.AboutBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="About Media Checker" Height="300" Width="400" ResizeMode="NoResize"
Icon="/MediaCheckerWPF;component/Resources/checker.ico"
ShowInTaskbar="False">
<Grid>
...
</Grid>
</Window>
Your first.xaml has the button e.g.:
<Button Height="23" HorizontalAlignment="Right" Name="aboutButton"
VerticalAlignment="Top" Width="23" Click="AboutButton_Click"
Content="{DynamicResource TInformationButton}"
ToolTip="{DynamicResource TInformationButtonTooltip}" Margin="0,0,8,0"/>
Then in the code behind:
private void AboutButton_Click(object sender, RoutedEventArgs e)
{
var about = new AboutBox { Owner = this };
about.Initialise();
about.Show();
}
ChrisF's answer is a good way of popping up a new window in a Windows-style application, except you should not call Initialize that way (it should be called from the constructor).
If you want web-style navigation instead, you should use the Page class instead of Window, along with NavigationService. This also allows your WPF application to run inside an actual web browser.