MouseDragElementBehavior in UWP - c#

I am currently porting an old game made for Windows Phone 8 in WPF/Silverlight to Universal Windows Platform. I have made letters that you can move in a canvas using MouseDragElementBehavior class. Is there any similar in UWP for this class?

There is an event called ManipulationDelta which is suggested in the comments. Here is how you can use it:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Canvas>
<TextBlock
FontSize="64"
ManipulationDelta="LetterA_ManipulationDelta"
ManipulationMode="All"
RenderTransformOrigin="0.5,0.5"
Text="A">
<TextBlock.RenderTransform>
<TranslateTransform x:Name="dragLetterA" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock
FontSize="64"
ManipulationDelta="LetterB_ManipulationDelta"
ManipulationMode="All"
RenderTransformOrigin="0.5,0.5"
Text="B">
<TextBlock.RenderTransform>
<TranslateTransform x:Name="dragLetterB" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock
FontSize="64"
ManipulationDelta="LetterC_ManipulationDelta"
ManipulationMode="All"
RenderTransformOrigin="0.5,0.5"
Text="C">
<TextBlock.RenderTransform>
<TranslateTransform x:Name="dragLetterC" />
</TextBlock.RenderTransform>
</TextBlock>
</Canvas>
</Grid>
Code behind looks like this:
private void LetterA_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
dragLetterA.X += e.Delta.Translation.X;
dragLetterA.Y += e.Delta.Translation.Y;
}
private void LetterB_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
dragLetterB.X += e.Delta.Translation.X;
dragLetterB.Y += e.Delta.Translation.Y;
}
private void LetterC_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
dragLetterC.X += e.Delta.Translation.X;
dragLetterC.Y += e.Delta.Translation.Y;
}
As simple as that.
Hope this helps.

Related

How can change position of canvas in WPF?

How can change runtime position of a canvas in which dynamically I added controls like (labels, lines)?
I can zoom canvas with all controls but I can't move in another position with MouseMove, MouseUp, MouseDown.
<Canvas Name="canvas" Width="1000" Height="400"
Margin="100 0 0 50"
Background="White"
VerticalAlignment="Bottom"
HorizontalAlignment="Center"
MouseWheel="Canvas_MouseWheel"
MouseMove="Canvas_MouseMove"
MouseUp="Canvas_MouseUp"
MouseDown="Canvas_MouseDown">
<Canvas.RenderTransform>
<ScaleTransform x:Name="st" />
</Canvas.RenderTransform>
</Canvas>
I find this code in internet but for my case is not working
bool activated;
Point point;
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
activated = true;
point = Mouse.GetPosition(canvas);
Mouse.Capture(canvas);
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (activated)
{
double top = Canvas.GetTop(canGraph) + Mouse.GetPosition(canvas).Y - point.Y;
Canvas.SetTop(canvas, top);
double left = Canvas.GetLeft(canvas) + Mouse.GetPosition(canvas).X - point.X;
Canvas.SetLeft(canvas, left);
point = Mouse.GetPosition(canvas);
}
}
private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
activated = false;
Mouse.Capture(null);
}
Edit - The previous solution that I provided was not going to work after the first move of the element without more code so here's a better one
In order to be working correctly the canvas element have to be aligned to the coordinate system of it's parent, which we achieve as we put the canvas in top left corner, if you don't put it there you have to calculate the difference yourselve.
Code behind
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
canvas.CaptureMouse();
}
Stopwatch sw = new Stopwatch();
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (canvas.IsMouseCaptured)
{
translate.X = e.GetPosition(container).X;
translate.Y = e.GetPosition(container).Y;
}
}
private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
canvas.ReleaseMouseCapture();
}
XAML
<Grid Background="Green" x:Name="container">
<Canvas Name="canvas" Width="100" Height="100"
Margin="0 0 0 0"
Background="Purple"
VerticalAlignment="Top"
HorizontalAlignment="Left"
MouseMove="Canvas_MouseMove"
MouseDown="Canvas_MouseDown">
<StackPanel Background="White">
<TextBlock >asdasda</TextBlock>
<TextBlock >cccc</TextBlock>
<TextBlock >aaaaa</TextBlock>
<TextBlock >bbbb</TextBlock>
</StackPanel>
<Canvas.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="st" />
<TranslateTransform x:Name="translate" />
</TransformGroup>
</Canvas.RenderTransform>
</Canvas>
</Grid>
Original answer
XAML
I'd do something like this:
Add a translate transform and to keep you previous transform put it in a group
Use translate transform in order to move the canvas with positions from the mouse events
For starting point of your translations you can use coordinates in the container
Code behind:
bool activated;
Point point;
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
activated = true;
point = e.GetPosition(container);
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (activated)
{
translate.X = e.GetPosition(container).X - point.X;
translate.Y = e.GetPosition(container).Y - point.Y;
}
}
private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
activated = false;
}
XAML
<Canvas Name="canvas" Width="100" Height="100"
Margin="0 0 0 0"
Background="Purple"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
MouseMove="Canvas_MouseMove"
MouseUp="Canvas_MouseUp"
MouseDown="Canvas_MouseDown">
<Canvas.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="st" />
<TranslateTransform x:Name="translate" />
</TransformGroup>
</Canvas.RenderTransform>
</Canvas>
</Grid>
After mouse down then again I move the canvas is start to move from first position when is been.
P.s.
I add this for more stable code , but always return back to the first position
private void Canvas_MouseLeave(object sender, MouseEventArgs e)
{
activated = false;
}

How to add scrolling/moving text in textblock in xaml

I want to add a scrolling/moving text(from right to left) in the textblock.
It should scroll one time only.
I have Googled it but didn't find anything.
I want to scroll the text in the textblock (not the whole textblock) only once. Then scrolling should be stopped.
I found this code on net but it is not what I want. I want to scroll the text 1 time and then stop scrolling. Any idea how to do that?
<TextBlock FontSize="22" x:Name="txtScrolling" Margin="1386,208,-616,460">
<TextBlock.RenderTransform>
<TranslateTransform x:Name="translate" />
</TextBlock.RenderTransform>
<TextBlock.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="1">
<DoubleAnimation
From="1000" To="-1000"
Storyboard.TargetName="translate"
Storyboard.TargetProperty="X"
Duration="0:0:10" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
This is the Text to Scroll
</TextBlock>
You could try something like this..
This is an xaml example:
<Grid>
<ScrollViewer x:Name="Scroll_Content" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto" CanContentScroll="True" VerticalAlignment="Center" HorizontalAlignment="Center" Width="250" FlowDirection="RightToLeft">
<TextBlock Text="Hello World ------------ Hello World ------------ Hello World -------- Hello World"></TextBlock>
</ScrollViewer>
<Button x:Name="Start_Timer" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,10" Width="100" Height="50" Content="Start Timer" Click="Start_Timer_Click"/>
</Grid>
Code behind:
DispatcherTimer timer1 = new DispatcherTimer();
double num = 0;
public MainWindow()
{
InitializeComponent();
timer1.Interval = new TimeSpan(0,0,0,0,250);
timer1.Tick += timer1_Tick;
}
void timer1_Tick(object sender, EventArgs e)
{
try
{
Scroll_Content.ScrollToHorizontalOffset(num);
num++;
}
catch { }
}
void Start_Timer_Click(object sender, RoutedEventArgs e)
{
if (timer1.IsEnabled == false)
{
num = 0;
timer1.Start();
}
else
timer1.Stop();
}

WinRT - App bar not appearing when I tap the ellipses

I'm trying to get my app bar to appear when I tap the 3 dots at the bottom of the screen, but when I do so it doesn't happen. Anyone know why & how this problem can be rectified?
MainPage.xaml
<Page
x:Name="pageRoot"
x:Class="HP.MainPage"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Exits_Expert_London_Lite.Lines_and_Stations.WC"
xmlns:common="using:Exits_Expert_London_Lite.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:q42controls="using:Q42.WinRT.Controls"
mc:Ignorable="d">
<Grid Background="Black">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid Name="CustomAppBarRoot" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Loaded="CustomAppBarRoot_OnLoaded"
ManipulationMode="TranslateY"
ManipulationDelta="CustomAppBarRoot_OnManipulationDelta"
ManipulationCompleted="CustomAppBarRoot_OnManipulationCompleted"
Tapped="CustomAppBarRoot_OnTapped">
<Grid.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Grid.RenderTransform>
<Grid.Background>
<SolidColorBrush Color="Black" Opacity="0.5"></SolidColorBrush>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Name="DotsTextBlock" FontSize="28" Text="..." HorizontalAlignment="Right" VerticalAlignment="Top"
Margin="0 0 15 0" Tapped="DotsTextBlock_OnTapped" Width="50" Height="50" TextAlignment="Center">
<TextBlock.RenderTransform>
<TranslateTransform Y="0" X="11"/>
</TextBlock.RenderTransform>
</TextBlock>
<StackPanel Name="ButtonsStackPanel" Grid.Row="1" Orientation="Horizontal">
<AppBarButton Label="tfg" Icon="Add"/>
<AppBarButton Label="tfg" Icon="Add"/>
</StackPanel>
</Grid>
<Hub>
<Hub.Header>
<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Margin="-1,-1,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
Style="{StaticResource NavigationBackButtonNormalStyle}"
VerticalAlignment="Top"
AutomationProperties.Name="Back"
AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button"/>
<TextBlock x:Name="pageTitle" Text="Page name" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Top"/>
</Grid>
</Hub.Header>
<HubSection Width="800" Padding="40,50,0,0">
<HubSection.Header>
<StackPanel>
<TextBlock Text="hub section 1" Style="{StaticResource HeaderTextBlockStyle}"/>
</StackPanel>
</HubSection.Header>
<DataTemplate>
<Grid>
<StackPanel>
<TextBlock Style="{StaticResource SubheaderTextBlockStyle}" Margin="0,0,0,5" TextWrapping="Wrap">
<Run Text="Hello World"/>
</TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</HubSection>
</Hub>
</Grid>
</Page>
MainPage.cs
using HP.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;
// The Hub Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=321224
namespace HP
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.Tapped += Page_OnTapped;
}
private void Page_OnTapped(object sender, TappedRoutedEventArgs tappedRoutedEventArgs)
{
if ( isAppBarShown )
HideCustomAppBar();
}
#region custom app bar
private Storyboard hideCustomAppBarStoryboard;
private Storyboard showCustomAppBarStoryboard;
private Size appBarSize;
private Size appBarButtonsSize;
private bool isAppBarShown = true;
private void CustomAppBarRoot_OnLoaded(object sender, RoutedEventArgs e)
{
appBarSize = new Size(CustomAppBarRoot.ActualWidth, CustomAppBarRoot.ActualHeight);
appBarButtonsSize = new Size(ButtonsStackPanel.ActualWidth, ButtonsStackPanel.ActualHeight);
InitializeStoryboards();
HideCustomAppBar();
}
private void ShowCustomAppBar()
{
isAppBarShown = true;
showCustomAppBarStoryboard.Begin();
}
private void HideCustomAppBar()
{
isAppBarShown = false;
hideCustomAppBarStoryboard.Begin();
}
private void DotsTextBlock_OnTapped(object sender, TappedRoutedEventArgs e)
{
if (isAppBarShown)
HideCustomAppBar();
else
ShowCustomAppBar();
}
private void InitializeStoryboards()
{
hideCustomAppBarStoryboard = new Storyboard();
showCustomAppBarStoryboard = new Storyboard();
var showDoubleAnimation = new DoubleAnimation()
{
EasingFunction = new CircleEase() {EasingMode = EasingMode.EaseInOut},
To = 0,
Duration = new Duration(TimeSpan.FromMilliseconds(200))
};
var hideDoubleAnimation = new DoubleAnimation()
{
EasingFunction = new CubicEase() {EasingMode = EasingMode.EaseInOut},
To = appBarButtonsSize.Height,
Duration = new Duration(TimeSpan.FromMilliseconds(200))
};
hideCustomAppBarStoryboard.Children.Add(hideDoubleAnimation);
showCustomAppBarStoryboard.Children.Add(showDoubleAnimation);
Storyboard.SetTarget(hideCustomAppBarStoryboard, CustomAppBarRoot);
Storyboard.SetTarget(showCustomAppBarStoryboard, CustomAppBarRoot);
Storyboard.SetTargetProperty(showCustomAppBarStoryboard, "(UIElement.RenderTransform).(TranslateTransform.Y)");
Storyboard.SetTargetProperty(hideCustomAppBarStoryboard, "(UIElement.RenderTransform).(TranslateTransform.Y)");
}
#endregion
private void CustomAppBarRoot_OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
var translateTransform = (CustomAppBarRoot.RenderTransform as TranslateTransform);
double newY = e.Delta.Translation.Y + translateTransform.Y;
translateTransform.Y = Math.Max(0, Math.Min(newY, appBarButtonsSize.Height));
}
private void CustomAppBarRoot_OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
// if small appbar-position changes are made app bar should back to previous position, just like in windows phone
if (Math.Abs(e.Cumulative.Translation.Y) < 20)
isAppBarShown = !isAppBarShown;
if (!isAppBarShown)
ShowCustomAppBar();
else
HideCustomAppBar();
}
private void CustomAppBarRoot_OnTapped(object sender, TappedRoutedEventArgs e)
{
e.Handled = true; // prevents raising Page.Tapped event so appbar won't be closed on AppBar-area tap
}
}
}
Move your CustomAppBarRoot Grid after the Hub control so it renders on top. As is, the Hub control covers the CustomAppBarRoot so clicks on the ellipses go to the Hub not to the DotsTextBlock. If you give the Hub a background colour for testing this is quite obvious (leave the Background off for production):
<Hub Background="Magenta">
You could also raise the CustomAppBarRoot in the Z-order by applying the Canvas.ZIndex property; however, since your CustomAppBarRoot isn't in a Canvas this is an off-label use so I'd prefer placing the CustomAppBarRoot after the Hub in the Xaml:
<Grid Name="CustomAppBarRoot" Canvas.ZIndex="100" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Loaded="CustomAppBarRoot_OnLoaded"
There is a Segoe UI Symbol for the "More" ellipses at Unicode 0xe10c that you might use rather than using a string of periods:
<TextBlock Name="DotsTextBlock" Text="" FontSize="14" FontFamily="Segoe UI Symbol" HorizontalAlignment="Right" VerticalAlignment="Top"
Margin="0 0 15 0" Tapped="DotsTextBlock_OnTapped" Width="50" Height="50" TextAlignment="Center">
<TextBlock.RenderTransform>
<TranslateTransform Y="0" X="11"/>
</TextBlock.RenderTransform>
</TextBlock>

Move ToolTip in WinRT

In WinRT (Windows Store Apps), I create a tooltip and set it to an element like this:
dragTip = new ToolTip();
dragTip.Content = "Test";
ToolTipService.SetToolTip(element as DependencyObject, dragTip);
dragTip.IsOpen = true;
I want to move this ToolTip as the mouse moves. Is there a way to do that? Or another alternative? I want to show a hint to the user as he/she drags an element.
Update
Here's the approach I took based on #Sajeetharan's suggestion:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" PointerMoved="homeGrid_PointerMoved" x:Name="homeGrid">
....
<GridView x:Name="content" CanDragItems="True" DragItemsStarting="content_DragItemsStarting">
...
</GridView>
<Popup Name="DeepZoomToolTip">
<Border CornerRadius="1" Padding="1" IsHitTestVisible="False">
<TextBlock Text="Here is a tool tip" />
</Border>
</Popup>
....
</Grid>
private void content_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
DeepZoomToolTip.IsOpen = true;
}
private void homeGrid_PointerMoved(object sender, PointerRoutedEventArgs e)
{
var position = e.GetCurrentPoint(homeGrid).Position;
DeepZoomToolTip.HorizontalOffset = position.X;
DeepZoomToolTip.VerticalOffset = position.Y;
}
Notice that the tooltip will move but not when the item is being dragged.
You can do this by using a popup control , Here is the full Thread how to make tooltip move along with mouse
XAML:
<Canvas x:Name="LayoutRoot" Background="White">
<Image Source="/sam.png" MouseMove="Image_MouseMove" MouseLeave="Image_MouseLeave"/>
<Popup Name="DeepZoomToolTip">
<Border CornerRadius="1" Padding="1" IsHitTestVisible="False">
<TextBlock Text="Here is a tool tip" />
</Border>
</Popup>
</Canvas>
private void Image_MouseMove(object sender, MouseEventArgs e)
{
DeepZoomToolTip.IsOpen = true;
DeepZoomToolTip.HorizontalOffset = e.GetPosition(LayoutRoot).X;
DeepZoomToolTip.VerticalOffset = e.GetPosition(LayoutRoot).Y;
}
private void Image_MouseLeave(object sender, MouseEventArgs e)
{
DeepZoomToolTip.IsOpen = false;
}

How to move 2 images at the same time in C# for Windows Phone App?

I have 2 images barTop and barBottom. If I drag the barTop, I want barBottom to be dragged along too. The codes that I have is below. May I know how can I do it?
private void GestureListener_DragDelta(object sender, DragDeltaGestureEventArgs e)
{
barTopTT.X += e.HorizontalChange;
barTopTT.Y += e.VerticalChange;
barBottomTT.X += e.HorizontalChange;
barBottomTT.Y += e.VerticalChange;
}
Try this,
<Image Height="100" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" Name="img1" Margin="0,0,0,0" Stretch="Uniform" Source="/1.png">
<Image.RenderTransform>
<CompositeTransform x:Name="img1gesture"/>
</Image.RenderTransform>
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta_1"/>
</toolkit:GestureService.GestureListener>
</Image>
<Image Height="100" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" Name="img2" Margin="0,0,0,0" Stretch="Uniform" Source="/1.png">
<Image.RenderTransform>
<CompositeTransform x:Name="img2gesture"/>
</Image.RenderTransform>
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragDelta="GestureListener_DragDelta_1"/>
</toolkit:GestureService.GestureListener>
</Image>
In C#,
private void GestureListener_DragDelta_1(object sender, Microsoft.Phone.Controls.DragDeltaGestureEventArgs e)
{
img1gesture.TranslateX += e.HorizontalChange;
img2gesture.TranslateX += e.HorizontalChange;
img1gesture.TranslateY += e.VerticalChange;
img2gesture.TranslateY += e.VerticalChange;
}

Categories