How to switching between InkCanvas and Canvas in UWP - xaml

I'm struggling with new UWP InkCanvas for my apps.If you are familiar with the new InkCanvas in UWP, I would truly appreciate your help.
I have a UWP apps need to switching between InkCanvas and Canvas, which I wish to use InkCanvas for Drawing, Canvas for creating Contents such as RichEditbox, Image, etc...
My XAML is below
<Grid Margin="100,0,100,0" Background="White" x:Name="MainGrid" PointerMoved="MyCanvas_PointerMoved" PointerReleased="MyCanvas_PointerReleased" PointerPressed="MyCanvas_PointerPressed">
<Canvas x:Name="MyCanvas" />
<InkCanvas x:Name="inkCanvas" Canvas.ZIndex="0" />
<!-- End "Step 2: Use InkCanvas to support basic inking" -->
</Grid>
I tried to make my Canvas ZIndex greater than InkCanvas by using
private void AppBarButton_Click(object sender, RoutedEventArgs e)
{
if(Canvas.GetZIndex(MyCanvas) > 1)
{
Canvas.SetZIndex(MyCanvas, 0);
}
else
{
Canvas.SetZIndex(MyCanvas, 5);
}
}
However I can't make my Canvas come to the front, the InkCanvas keep Capturing my stroke if I Draw on it instead.
Does anyone know how to switch the Canvas and InkCanvas in my Grid without changing the Visibility of my InkCanvas to Collapsed?

By default the Canvas background is empty (null), so it will not capture pointer input and will pass it through to the InkCanvas.
If you want to prevent this, you could set its Background to Transparent.
However, when you start putting some controls on the Canvas itself, they should capture the pen input and not let it through to the InkCanvas.

Related

XAML : Binding FontSize to the Height of Control

Within a Xamarin.Form page, I am trying to bind the FontSize of a label to the height of that same label.
I seen examples in WPF that do this:
FontSize="{Binding ElementName=CurrentPresenter, Path=Height}"
But I can not seem to get anything to work like that in Forms, i.e.:
<Label
Text="X"
FontSize="{Binding ElementName=CurrentPresenter, Path=RequestedHeight}"
HorizontalTextAlignment="Center"
AbsoluteLayout.LayoutBounds="0.1, 0.5, 0.33, 0.66"
AbsoluteLayout.LayoutFlags="All" />
(I will use a data converter to adjust the font size so based upon screen DPI, I can auto-adjust, but for now, I'm just trying to bind it to a control's height to get something other than default system font size)
This way appears to work fine, not sure about the runtime layout performance though...
FYI: This does not work within the XAML Designer, only runtime
<Label
Text="X"
x:Name="foo"
BindingContext="{x:Reference Name=foo}"
FontSize="{Binding Path=Height}"
HorizontalTextAlignment="Center"
AbsoluteLayout.LayoutBounds="0.1, 0.5, 0.33, 0.66"
AbsoluteLayout.LayoutFlags="All" />
Not exactly related to OP question but searching "Xaml height based on another control" has hardly any results in Google so posting this in case it helps someone else.
To change the size of smaller buttons to match the size of a larger button like in the following picture
There are several ways to do this without using code behind but if the layout you are trying to use is being difficult here following is another option. To change the size of the smaller buttons without changing the binding of those controls you can give the buttons names in XAML and then do something like this in the code behind:
public HomeOpenPage ()
{
InitializeComponent ();
RefreshButton.PropertyChanging += RefreshButton_PropertyChanging;
}
private void RefreshButton_PropertyChanging(object sender, PropertyChangingEventArgs e)
{
if (RefreshButton.Width != -1)
{
var width = RefreshButton.Width;
CSVButton.WidthRequest = width;
EndButton.WidthRequest = width;
}
}
protected override void OnDisappearing()
{
RefreshButton.PropertyChanging -= RefreshButton_PropertyChanging;
base.OnDisappearing();
}

Image translation is clipped (how to prevent)

How can I force a UI object to NOT be clipped when it's partly outside the screen. I have an image that doesn't fit inside the screen completely. When I drag it (TranslateY) it moves like it's supposed to but the problem is that the part that was outside the screen doesn't appear so the image is abruptly cut. The only part of the image that is visibly moving is the part that originally fit to the screen.
Ps. Please do not recommend scollviewer as this is about a gesture to do a specific thing on the UI and ScrollViewer is not ok for that.
This is basically the XAML (The image is twice the height of the display)
<Grid x:Name="GestureScreen" ManipulationMode="TranslateY" RenderTransformOrigin="0.5,0.5">
<Image x:Name="GestureImage" CacheMode="BitMapCache" Source="Assets/bg/draggable.png" />
</Grid>
This is the C# (not really relevant, but still)
void GestureScreen_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
move.Y += e.Delta.Translation.Y;
}
Specify a row and column for the image which directly specifies Auto for both. That way the image will size to its actual size and not the current size of the * defaults of the screen size. Hence you will have the whole image as dragged.

What is the difference between null and transparent brush in the Background or Fill

For example we have a Border. What the difference beetween these XAMLs?
1) Background="Transparent"
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Border
BorderBrush="White"
BorderThickness="2"
Width="400"
Height="400"
Background="Transparent"
PointerPressed="Border_PointerPressed"
PointerReleased="Border_PointerReleased" />
</Grid>
2) Background="{x:Null}"
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Border
BorderBrush="White"
BorderThickness="2"
Width="400"
Height="400"
Background="{x:Null}"
PointerPressed="Border_PointerPressed"
PointerReleased="Border_PointerReleased" />
</Grid>
Both of these borders looks identical. But what the difference?
The difference is if we set null background the Border will not support hit-testing, that's why routed events like PonterPressed will not be raised.
Conversely though, if we set Transparent background events will be raised.
To illustrate this let's write code-behind.
using Windows.UI.Xaml.Media;
namespace App1 {
public sealed partial class MainPage : Page {
public MainPage() {
this.InitializeComponent();
}
void Border_PointerPressed(object sender, PointerRoutedEventArgs e) {
Border border = sender as Border;
if (border != null)
border.Background = new SolidColorBrush(Colors.Red);
}
void Border_PointerReleased(object sender, PointerRoutedEventArgs e) {
Border border = sender as Border;
if (border != null)
border.Background = new SolidColorBrush(Colors.Transparent);
}
}
}
1) Let's use the first XAML, compile our app and run it. Try to tap inside the square. The square becomes red because the events are rised and the handlers calls.
2) Now let's use the second XAML, compile the app, run it, tap inside the square. Nothing happens because the events are not rised. The handlers are not calls.
For completeness, I found this link http://msdn.microsoft.com/en-us/library/hh758286.aspx#hit_testing explaining this rather well - see especially the second bullet point:
Hit testing and input events
Determining whether and where in UI an element is visible to mouse,
touch, and stylus input is called hit testing. For touch actions and
also for interaction-specific or manipulation events that are
consequences of a touch action, an element must be hit-test visible in
order to be the event source and fire the event that is associated
with the action. Otherwise, the action passes through the element to
any underlying elements or parent elements in the visual tree that
could interact with that input. There are several factors that affect
hit testing, but you can determine whether a given element can fire
input events by checking its IsHitTestVisible property. This property
returns true only if the element meets these criteria:
The element's Visibility property value is Visible.
The element's Background or Fill property value is not null. A null Brush value results in transparency and hit test invisibility. (To
make an element transparent but also hit testable, use a Transparent
brush instead of null.) Note Background and Fill aren't defined by
UIElement, and are instead defined by different derived classes such
as Control and Shape. But the implications of brushes you use for
foreground and background properties are the same for hit testing and
input events, no matter which subclass implements the properties.
If the element is a control, its IsEnabled property value must be true.
The element must have actual dimensions in layout. An element where either ActualHeight and ActualWidth are 0 won't fire input events.

manipulationdelta for popup window - XAML Windows 8

I am trying to put floating popup windows on screen. I want user to be able to move that popup window anywhere on the screen.
And so I am using:
<Popup x:Name="myPopup" Grid.Row="0" Grid.RowSpan="2" Margin="0, 0, 0, 0" ManipulationMode="All" ManipulationDelta="PopupManipulationDelta" IsLightDismissEnabled="False" Visibility="Collapsed" IsOpen="false">
code behind:
private void PopupManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
var ct = (CompositeTransform)addShapesPopup.RenderTransform;
ct.TranslateX += e.Delta.Translation.X;
ct.TranslateY += e.Delta.Translation.Y;
UpdateLayout();
}
But this is not working. The function PopupManipulationDelta is not even getting called.
I tried using same logic on shapes like rectangle, ellipse and it works fine there.
Can you please help me understand why it's not working with popup?
Thank you.
I believe a Popup does not have any visual representation, so it can't respond to hit testing and thus to manipulation events. Simply put some control inside of it and have that respond to the input events. It can be a Grid with Background="Transparent" if you don't want it to be visible.

Zooming in and out in Grid, Images on WinRT (Metro style app)

I'm trying to implement something in my app, I need to show an image, and let the user pinch in and out of the images.
I think its possible using the ScrollViewer, but I couldnt get it to work, help?
I hate to oversimplify this, but the WinRT XAML ScrollViewer has gesture manipulation built in.
You can see what I mean here. This might not be what you want. But it's sure a simple approach and might fit a certain % of scenarios. Maybe even yours.
Controls that incorporate a ScrollViewer in compositing often set a value for ZoomMode in the default template and starting visual states, and it is this templated value that you will typically start with. Controls with a ScrollViewer as part of their composition typically use template binding such that setting the attached property at the level of the control will change the scroll behavior of the ScrollViewer part within the control. Otherwise, it may be necessary to replace the template in order to change the scroll behavior of a ScrollViewer part.
Check out Morten Nielsen's article on Building A Multi-Touch Photo Viewer Control. It's for Silverlight/Windows Phone, but if you just enable manipulations on the image and change a few types in manipulation events - it should work great.
A simple solution that might be enough for you is to just put the image in a ScrollViewer, although to see it working - you need a touch screen or run it in a simulator (use the pinch tool, then drag and scroll on the image to zoom in/out).
You can also zoom it with code:
<Grid
Background="{StaticResource ApplicationPageBackgroundBrush}">
<ScrollViewer
x:Name="myScrollViewer">
<Image
Source="/Assets/SplashScreen.png" />
</ScrollViewer>
</Grid>
.
public BlankPage()
{
this.InitializeComponent();
myScrollViewer.ZoomMode = ZoomMode.Enabled; // default
Test();
}
private async void Test()
{
while (true)
{
for (double x = 0; x < 2 * Math.PI; x += Math.PI / 30)
{
await Task.Delay(1000 / 30);
float factor = (float)(1.0 + Math.Sin(x) / 10);
myScrollViewer.ZoomToFactor(factor);
}
}
}