I am quite noob in WPF. I am creating a WPF application and using a EmguCV library for image Processing. I found that I can't use ImageBox in WPF. So I am using NamedWindow to show image then I decided to use Image Controlto show the image on the window. I am trying to draw the rectangle over that image but rectangle in not drawn at other place. So can anyone tell me what is wrong in the code.
Basically I want to take ROI of that image.
EDIT:-
I put the Canvas inside grid a put the Image Control inside that Canvas
**My XAML Code **
<Grid Margin="0,0,2,-1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="138*"/>
<ColumnDefinition Width="139*"/>
</Grid.ColumnDefinitions>
<Button x:Name="button" Content="Convert" Margin="139.053,432.066,0,0" Click="button_Click" Height="27.934" VerticalAlignment="Top" HorizontalAlignment="Left" Width="113.947" Grid.Column="1"/>
<Button x:Name="button1" Content="Load Palette" Margin="308,432.066,0,0" Click="button1_Click_1" Height="27.934" VerticalAlignment="Top" HorizontalAlignment="Left" Width="75" Grid.ColumnSpan="2"/>
<Button x:Name="button2" Content="Load Gray Image" Margin="48,432.066,0,0" Click="button2_Click" Height="27.934" VerticalAlignment="Top" HorizontalAlignment="Left" Width="104"/>
<Canvas x:Name="MyCanvas" Margin="81,86.5,27.245,120.5" Grid.Column="1">
<Image x:Name="image3" Height="263" Width="238"/>
</Canvas>
<Image x:Name="image1" HorizontalAlignment="Left" Height="263" Margin="10,86.5,0,0" VerticalAlignment="Top" Width="255.5"/>
<Image x:Name="image2" Grid.ColumnSpan="2" HorizontalAlignment="Left" Height="393" Margin="308,10,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
And My C# code is
private Boolean isdragging = false;
private System.Windows.Point startPoint;
private System.Windows.Point endPoint;
private System.Windows.Shapes.Rectangle rect;
private void image3_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
startPoint = e.GetPosition(MyCanvas);
isdragging = true;
if(rect != null)
MyCanvas.Children.Remove(rect);
rect = new System.Windows.Shapes.Rectangle
{
Stroke = System.Windows.Media.Brushes.LightBlue,
StrokeThickness = 2
};
System.Windows.Controls.Canvas.SetLeft(rect, startPoint.X);
System.Windows.Controls.Canvas.SetTop(rect, startPoint.Y);
MyCanvas.Children.Add(rect);
}
private void image3_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
rect = null;
isdragging = false;
endPoint = e.GetPosition(MyCanvas);
}
private void image3_MouseMove(object sender, MouseEventArgs e)
{
if (isdragging == true)
{
var pos = e.GetPosition(MyCanvas);
var x = Math.Min(pos.X, startPoint.X);
var y = Math.Min(pos.Y, startPoint.Y);
var w = Math.Max(pos.X, startPoint.X) - x;
var h = Math.Max(pos.Y, startPoint.Y) - y;
rect.Width = w;
rect.Height = h;
System.Windows.Controls.Canvas.SetLeft(rect, x);
System.Windows.Controls.Canvas.SetTop(rect, y);
}
}
I am using Event Handler over the Canvas but it doesn't showing the rectangle
Thanks in Advance
Thanks Clemens, I have got the answer, Actually I haven't add the event handler to image3 Image Control that's why it is not showing the output.
<Canvas x:Name="MyCanvas" Margin="81,86.5,27.245,120.5" Grid.Column="1">
<Image x:Name="image3" Height="263" Width="238" MouseLeftButtonDown="image3_MouseLeftButtonDown" MouseLeftButtonUp="image3_MouseLeftButtonUp" MouseMove="image3_MouseMove"/>
</Canvas>
Related
I'm trying to implement some WPF drawing sample to understand how it works. I can solve such task with C++ very quickly but I want to understand WPF means.
During the implementation of a task I faced with some strange problem: coordinates shift of mouse cursor responsible to pixels I can see on canvas.
First of all, my task is: load some picture from file; show it on Image component; allow to draw over image with mouse (like pencil tool); save changes to new file. Task is easy to implement.
Here is my code:
XAML:
<Window x:Class="MyPaint.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:MyPaint"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Background="#FF000000"
mc:Ignorable="d"
Title="Strange Paint" Height="503.542" Width="766.281" Icon="icons/paint.png">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Column="0" Grid.Row="1" Width="Auto">
<StackPanel HorizontalAlignment="Left" Width="Auto" Background="{x:Null}">
<Button x:Name="arrowButton" Width="25" Height="25" HorizontalAlignment="Left" Click="ArrowButton_Click">
<Image Source="icons/arrow.png"/>
</Button>
<Button x:Name="selectorButton" Width="25" Height="25" Click="SelectorButton_Click" HorizontalAlignment="Left">
<Image Source="icons/select_selection_tool-128.png"/>
</Button>
<Button x:Name="clearButton" Width="25" Height="25" Click="ClearButton_Click" HorizontalAlignment="Left">
<Image Source="icons/clear.png"/>
</Button>
<Button x:Name="pencilButton" Width="25" Height="25" Click="PencilButton_Click" HorizontalAlignment="Left">
<Image Source="icons/pencil.png"/>
</Button>
<Button x:Name="fillButton" Width="25" Height="25" Click="FillButton_Click" HorizontalAlignment="Left">
<Image Source="icons/fill.png"/>
</Button>
<xctk:ColorPicker Width="50" Name="ClrPcker_Foreground" SelectedColorChanged="ClrPcker_Foreground_SelectedColorChanged">
</xctk:ColorPicker>
</StackPanel>
</Grid>
<Grid x:Name="drawingCanvas" Grid.Column="1" Grid.Row="1" MouseMove="paintImageCanvas_MouseMove" MouseLeave="PaintImageCanvas_MouseLeave" MouseLeftButtonUp="PaintImageCanvas_MouseLeftButtonUp">
<ScrollViewer Grid.Column="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Canvas x:Name="scrCanvas" Width="{Binding ActualWidth, ElementName=paintImageCanvas}" Height="{Binding ActualHeight, ElementName=paintImageCanvas}" >
<Image x:Name="paintImageCanvas" HorizontalAlignment="Left" VerticalAlignment="Top" Stretch="UniformToFill" MouseDown="paintImageCanvas_MouseDown" MouseMove="paintImageCanvas_MouseMove">
</Image>
<Rectangle x:Name="Rect" Stroke="DarkOrange" Visibility="Collapsed" Fill="#77EEEEEE"></Rectangle>
</Canvas>
</ScrollViewer>
</Grid>
<StackPanel Grid.Row="0">
<Menu IsMainMenu="True" DockPanel.Dock="Top" Background="#FF000000">
<MenuItem Header="_File" Foreground="White" Background="#FF000000">
<MenuItem x:Name="newMenuItem" Header="_New" Background="#FF000000" Click="NewMenuItem_Click"/>
<MenuItem x:Name="openMenuItem" Header="_Open" Click="openMenuItem_Click" Background="#FF000000"/>
<MenuItem Header="_Close" Background="#FF000000"/>
<MenuItem Header="_Save" Background="#FF000000" Click="MenuItem_Click"/>
<MenuItem x:Name="exitMenuItem" Header="_Exit" Click="exitMenuItem_Click" Background="#FF000000"/>
</MenuItem>
</Menu>
<StackPanel></StackPanel>
</StackPanel>
</Grid>
Implementation of window class:
Class members:
Point currentPoint = new Point();
ToolBoxTypes currentSelectedTool = ToolBoxTypes.Unknown;
Color foregroundColor = Brushes.Black.Color;
WriteableBitmap imageWriteableBitmap;
Constructor and initialization (init white canvas 1024x768):
public MainWindow()
{
InitializeComponent();
ClrPcker_Foreground.SelectedColor = foregroundColor;
imageWriteableBitmap = BitmapFactory.New(1024, 768);
paintImageCanvas.Source = imageWriteableBitmap;
imageWriteableBitmap.Clear(Colors.White);
int i = 0;
}
Mouse down event (here I get the first point):
private void paintImageCanvas_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ButtonState == MouseButtonState.Pressed)
{
currentPoint = e.GetPosition(paintImageCanvas);
}
if (currentSelectedTool == ToolBoxTypes.PencilTool)
{
}
}
Mouse move event (draw on canvas if pressed):
private void paintImageCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
if(currentSelectedTool == ToolBoxTypes.PencilTool)
{
int x1 = Convert.ToInt32(currentPoint.X);
int y1 = Convert.ToInt32(currentPoint.Y);
int x2 = Convert.ToInt32(e.GetPosition(paintImageCanvas).X);
int y2 = Convert.ToInt32(e.GetPosition(paintImageCanvas).Y);
Console.WriteLine("Mouse X: " + x2 + " Mouse Y: " + y2);
imageWriteableBitmap.DrawLine( x1, y1, x2, y2, foregroundColor );
currentPoint = e.GetPosition(paintImageCanvas);
}
}
}
Ok. That's easy code.
And now, two usecases:
On start and init I can see white canvas and can draw with mouse without any problem (cursor follows pixels):
usecase 1
I loaded picture (size is 700x600) and got a problem, cursor has different place (can see a shift):
usecase 2
I think that problem is that canvas (Image) has different side than actual picture's side. I'm not sure.
Could you help me please to understand what is wrong and how to fix that?
Thanks.
Thanks to Dmitry (see comments on my question) the reason of the problem has been found: DPI of source picture.
I changed my code of picture loading and it works fine:
private void openMenuItem_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "JPEG files (*.jpg)|*.jpg|PNG files (*.png)|*.png";
if (openFileDialog.ShowDialog() == true)
{
BitmapImage image = new BitmapImage(new Uri(openFileDialog.FileName));
imageWriteableBitmap = new WriteableBitmap(image);
double dpi = 96;
int width = imageWriteableBitmap.PixelWidth;
int height = imageWriteableBitmap.PixelHeight;
int stride = width * 4;
byte[] pixelData = new byte[stride * height];
imageWriteableBitmap.CopyPixels(pixelData, stride, 0);
BitmapSource bmpSource = BitmapSource.Create(width, height, dpi, dpi, PixelFormats.Bgra32, null, pixelData, stride);
imageWriteableBitmap = new WriteableBitmap(
bmpSource.PixelWidth,
bmpSource.PixelHeight,
bmpSource.DpiX, bmpSource.DpiY,
bmpSource.Format, null);
imageWriteableBitmap.WritePixels(
new Int32Rect(0, 0, bmpSource.PixelWidth, bmpSource.PixelHeight), pixelData, stride, 0);
paintImageCanvas.Source = imageWriteableBitmap;
}
}
I'm making a Windows Desktop Application that have drag and drop functionality.
I'm using Polygon (And Images later) Shapes for drag and drop. The drag and drop functionality works fine but I want that if user drag any shape from the panel and when he drag other shape then the second shape automatically fix with first shape.
You'll understand it by take a look at below screenshots.
It is the Screen Shot of what happens when I drag Shapes
When user drop the polygon near the other polygon it will automatically adjust itself, if the same polygon drop in other area of canvas than a error will show to the user.
Here is my XAML Code
<Window x:Class="Images.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:Images"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<DockPanel
VerticalAlignment="Stretch"
Height="Auto">
<DockPanel
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="Auto"
MinWidth="400"
Margin="10">
<GroupBox
DockPanel.Dock="Left"
Width="350"
Background="Aqua"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
Height="Auto">
<WrapPanel Margin="0,10,0,0" VerticalAlignment="Top">
<Button Name="control" Content="Control" Height="30" Background="BlueViolet" Margin="5" Width="100"/>
<Button Name="motion" Content="Motion" Width="100" Margin="5" Background="Green" Height="30"/>
<Button Name="variable" Content="Variable" Width="100" Margin="5" Background="SeaGreen" Height="30"/>
<Button Name="sensor" Content="Sensor" Width="100" Margin="5" Background="OrangeRed" Height="30"/>
<Button Name="lcd" Content="LCD" Width="100" Margin="5" Height="30" Background="PaleVioletRed"/>
<Button Name="function" Content="Function" Width="100" Margin="5" Height="30" Background="Salmon"/>
<StackPanel Name="heaading" Width="350">
<TextBlock Name="controlName" TextAlignment="Center" Text="Controls"/>
</StackPanel>
<StackPanel Name="userControls" Orientation="Vertical">
<!-- Users Controls Items Goes Here -->
<Polygon Name="startProgram" Points="80,10, 80, 80, 135,80, 135, 45, 205, 45, 205, 80, 260, 80, 260,10" Fill="Chocolate" Stroke="Black" StrokeThickness="2" MouseLeftButtonDown="shape_MouseLeftButtonDown" />
<Polygon Name="endProgram" Fill="BlueViolet" Points="80,40, 80,80, 260,80, 260,40, 200,40, 200,10, 140,10,140,40" Stroke="Black" StrokeThickness="2" MouseLeftButtonDown="shape_MouseLeftButtonDown" />
</StackPanel>
</WrapPanel>
</GroupBox>
<!-- Change this to Canvas for work later -->
<Canvas x:Name="dropArea" DockPanel.Dock="Right" Margin="10" Background="#FF9760BF" Width="Auto" HorizontalAlignment="Stretch" AllowDrop="True" Drop="dropArea_Drop">
</Canvas>
</DockPanel>
</DockPanel>
</Window>
Here is my CS code
namespace Images
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void dropArea_Drop(object sender, DragEventArgs e)
{
var shape = e.Data.GetData(typeof(Polygon)) as Polygon;
Console.WriteLine("Polygon Name : " + shape.Name);
Polygon myPolygon = new Polygon();
myPolygon.Stroke = shape.Stroke;
myPolygon.Fill = shape.Fill;
myPolygon.StrokeThickness = 2;
Canvas.SetTop(myPolygon, e.GetPosition(dropArea).Y);
myPolygon.Points = shape.Points;
dropArea.Children.Add(myPolygon);
myPolygon.MouseRightButtonDown += new MouseButtonEventHandler(dragged_ShapeMouseDown);
}
private void dragged_ShapeMouseDown(object sender, MouseButtonEventArgs e)
{
//Show Options to Delete or set Value to current Polygon
}
private void shape_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Polygon shape = e.Source as Polygon;
DragDrop.DoDragDrop(shape, shape, DragDropEffects.Copy);
}
}
}
Problem
I'm using Canvas.setTop because without setting it my polygon show over the first.
Here I'm setting the polygon that fix with its above polygon but it can be left or right also as shown in below screenshot.
SOLUTION
For Deleting shape
myPolygon.MouseLeftButtonUp += new MouseButtonEventHandler(dragged_ShapeMouseDown);
private void dragged_ShapeMouseDown(object sender, MouseButtonEventArgs e)
{
if (dropArea.Children.Count > 0)
dropArea.Children.Remove(sender as Polygon);
}
Sacha Barber has got very nice article that describe exactly what you are trying to do i think...4 steps articles up to MVVM ! have a look these step1 and
step2, step3, step4 - I also used it in my own project ArchX
well, i think everything is there in my code : during onmove test the result and change the cursor. ondragend : use a HitHelper to determine where you release the mouse and return the shape his tested - then adjust the shape of the polygon regarding the hit result : below sample code - GuideLineManager
public Cursor HitTestGuide(Point p, RulerOrientation mode)
{
if (_Guides.Exists(g => (int)g.Info.Orientation == (int)mode && g.HitTest(p)))
{
return _Guides.First(g => (int)g.Info.Orientation == (int)mode && g.HitTest(p)).Cursor;
}
return Cursors.Arrow;
}
and the onDragEnd, call to get the hit tested object
public Guideline GetSnapGuide(Point hitPoint)
{
foreach (Guideline gl in Guides)
{
if (!gl.IsDisplayed) continue;
if (gl.Info.IsSnap && !gl.Info.IsMoving)
if (gl.IsOnGuide(hitPoint, _Container.dPicCapture))
{
return gl;
}
}
return null;
}
I have 10 rectangles inside the canvas, in the ManipulationDelta event, I have to change the height and width. It is working properly in the windows desktop but it takes some time in universal Windows device(phone) when manipulating the rectangle.How to smoothly manipulating the UI element in the windows device. Please suggest me, is any other way to solve this problem?
Here is my code:
<Canvas Name="LayoutRoot" Width="300" Height="500">
<Rectangle Fill="Red" Height="100" Width="100"/>
<Rectangle Fill="Red" Height="100" Width="100"/>
<Rectangle Fill="Red" Height="100" Width="100"/>
<Rectangle Fill="Red" Height="100" Width="100"/>
<Rectangle Fill="Red" Height="100" Width="100"/>
<Rectangle Fill="Red" Height="100" Width="100"/>
<Rectangle Fill="Red" Height="100" Width="100"/>
<Rectangle Fill="Red" Height="100" Width="100"/>
<Rectangle Fill="Red" Height="100" Width="100"/>
<Rectangle Fill="Green" Height="100" Width="100"/>
</Canvas>
private void MainPage_OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
foreach (Rectangle rectAngle in LayoutRoot.Children)
{
rectAngle.Width += e.Cumulative.Scale;
rectAngle.Height += e.Cumulative.Scale;
Canvas.SetLeft(rectAngle, LayoutRoot.Width / 2 - rectAngle.ActualWidth / 2);
Canvas.SetTop(rectAngle, LayoutRoot.Height / 2 - rectAngle.ActualHeight / 2);
}
}
You have to use RenderTransform like a TranslateTransform to move your elements, because they are not dependant properties and are performance oriented. So instead using the Canvas Top and Left properties set RenderTransformOrigin and a TranslateTransform.
You will notice a really increased performance.
private void MainPage_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
foreach (Rectangle child in LayoutRoot.Children)
{
child.Width += e.Cumulative.Scale;
child.Height += e.Cumulative.Scale;
//This is C#7 in case C#6 adapt
if(child.RenderTransform is TranslateTransform tf)
{
tf.X = LayoutRoot.Width / 2 - child.ActualWidth / 2;
tf.Y = LayoutRoot.Height / 2 - child.ActualHeight / 2;
}
}
}
private void Initialize()
{
var redbrush = new SolidColorBrush(Colors.Red);
foreach (Rectangle child in LayoutRoot.Children)
{
child.Fill = redbrush;
child.Height = 100;
child.Width = 100;
child.RenderTransformOrigin = new Point(0.5, 0.5);
child.RenderTransform = new TranslateTransform();
}
}
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>
In my XAML i have a listbox and some textboxes in a grid and a reactangle in a canvas:
Title="MainWindow" Height="350" Width="500" WindowStartupLocation="CenterScreen">
<Grid>
<ListBox HorizontalAlignment="Left"
Margin="12,12,0,12"
Name="listBoxContainer"
Width="120">
<ListBoxItem Content="Item1" />
<ListBoxItem Content="Item2" />
<ListBoxItem Content="Item3" />
</ListBox>
<TextBox Height="23"
Margin="138,12,85,0"
Name="textBoxAddress"
VerticalAlignment="Top" />
<TextBox Margin="138,41,85,12"
Name="textBoxMsg" />
<Button Content="Button"
Name="buttonAnimation"
Width="75"
Margin="0,10,5,0"
Height="23"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Click="Button1Click" />
<Canvas Name="CanvasAnimation">
<Rectangle Canvas.Left="408"
Canvas.Top="140"
Height="50"
Name="rectAnimation"
Stroke="Black"
Width="50" />
</Canvas>
</Grid>
From my code behind, i can move the rectangle from its position to a distance:
private void Button1Click(object sender, RoutedEventArgs e)
{
var trs = new TranslateTransform();
var anim3 = new DoubleAnimation(0, -200, TimeSpan.FromSeconds(2));
trs.BeginAnimation(TranslateTransform.XProperty, anim3);
trs.BeginAnimation(TranslateTransform.YProperty, anim3);
CanvasAnimation.RenderTransform = trs;
}
I would like to know how i can move the rectangle from its position to another position by coordinates? Like having the rectangle move to the position of the listbox or textbox
Please note that the below code assumes the coordinates for the button on the canvas and on the form are the same. This is not optimal, you should find a better solution, like putting the button on the canvas.
private void Button1Click(object sender, RoutedEventArgs e)
{
//Point relativePoint = buttonAnimation.TransformToAncestor(this).Transform(new Point(0, 0));
Point relativePoint = buttonAnimation.TransformToVisual(CanvasAnimation).Transform(new Point(0, 0));
var moveAnimX = new DoubleAnimation(Canvas.GetLeft(rectAnimation), relativePoint.X, new Duration(TimeSpan.FromSeconds(10)));
var moveAnimY = new DoubleAnimation(Canvas.GetTop(rectAnimation), relativePoint.Y, new Duration(TimeSpan.FromSeconds(10)));
rectAnimation.BeginAnimation(Canvas.LeftProperty, moveAnimX);
rectAnimation.BeginAnimation(Canvas.TopProperty, moveAnimY);
}
Sorry for the late answer, but it sounds like you want to set a dependency property.
rectAnimation.SetValue(Canvas.TopProperty, 0.0);
rectAnimation.SetValue(Canvas.LeftProperty, 0.0);
This will (instantly) place the rectangle at the top and left of the containing canvas.