Overlaying elements on image - c#

I have a grid containing an Image (with 2 rows top and bot that I will use later) and another grid containing 4 radio button.
When user click on image, a cross is displayed on the point where he clicked.
There is a part of code :
<Grid Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Image Grid.Row="0"
x:Name="ImageViewer"
Source="{Binding Picture}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
MouseDown="Image_MouseDown"
MouseMove="ImageViewer_MouseMove"
MouseUp="Image_MouseUp"/>
<local:Cross Grid.Row="0"
CenterPoint="{Binding Point1}"
Foreground="Red"/>
<!-- Grid.Row="1" - Grid with RadioButtons -->
</Grid>
With events :
protected bool StartMove = false;
private void Image_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
StartMove = true;
Point p = e.GetPosition(ImageViewer);
DrawPoint(p);
}
}
private void Image_MouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
StartMove = false;
}
}
private void ImageViewer_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && StartMove)
{
Point p = e.GetPosition(ImageViewer);
DrawPoint(p);
}
}
When image is perfectly sized (no border), the cross is correctly drawn. Clicking on my cat eye made this :
But if I resize my window, the cross is moving. I guess that the coordinates are computed considering the white spaces but I don't know how to prevent this.
There it is with the same point :

The cross is drawn by local:Cross element. This element layout is matching to Image and you expect it to draw cross relative to Image.
And it does.
The problem is what Image (disregards it's stretching its size) also stretching its source image. You can try to set Image.Stretch to Fill or solve the problem by using another layout (e.g. Stretch="None", making position and size of Cross and Image equal).

In fact, it is your image that is moving not the cross.
Your problem is that your are catching the position relative to Image UI element, so when you resize your main window you are also resizing your Image element.
Possible solutions:
Fixed size Image element
or, Recalculate the position of your cross when resize
or, Keep your image aligned to top left in your Image

Related

how to bubble pointer event to child overlapping each other in same parent

I have a situation where I have several images overlapping each other and on the pointer pressed I want to test if the clicked point is clicked on the transparent part of the image I want it to let go of the event and let the image below it test it out and repeat but it's passing the pointer event directly to the parent and remaining image is not being tested
<Grid Background="Red"
Width="200"
Height="200"
x:Name="grdRed"
PointerPressed="grdRed_PointerPressed"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Grid Background="Blue"
Width="150"
Height="150"
x:Name="grdBlue"
PointerPressed="grdBlue_PointerPressed"/>
<Grid Background="Green"
Width="100"
Height="100"
x:Name="grdGreen"
PointerPressed="grdGreen_PointerPressed"/>
</Grid>
private void grdRed_PointerPressed(object sender, PointerRoutedEventArgs e)
{
Debug.WriteLine("Red Pressed ");
e.Handled = false;
}
private void grdBlue_PointerPressed(object sender, PointerRoutedEventArgs e)
{
Debug.WriteLine("Blue Pressed ");
e.Handled = false;
}
private void grdGreen_PointerPressed(object sender, PointerRoutedEventArgs e)
{
Debug.WriteLine("Green Pressed ");
e.Handled = false;
}
now when I click the green Color Grid
output is
Green Pressed
Red Pressed
what I want is
Green Pressed
Blue Pressed
Red Pressed
but I want it to go through the blue grid since the blue grid is below the green one,
I'll set the e.Handled as per the calculation if the clicked part is transparent I'll set it to false else true then it should go to blue grid I'll test it again and so on
So the question is how can I make the event get passed through the blue grid currently it moving from child to parent directly
thanks

SKElement - Create x y scrollbar for image

I am a bit new to WPF. I wanted to make my image scrollable when I scale up the image. This is my XAML code.
<UserControl xmlns: skia="clr-namespace:SkiaSharp.Views.WPF:assembly=SkiaSharp.Views.WPF">
<Grid>
<skia:SKElement Name="Canvas" PaintSurface="SKElement_PaintSurface">
</Grid>
</UserControl>
private void SKElement_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
\\Code goes here...
}
Inside the SKElement_PaintSurface method, I created a way to draw the bitmap image on the canvas. But when I scale up the image I can't scroll the image. Does anyone know to create a scrollbar for this?
Put the Canvas in a ScrollViewer element and set its Height and/or Width when you scale it:
<UserControl xmlns: skia="clr-namespace:SkiaSharp.Views.WPF:assembly=SkiaSharp.Views.WPF">
<Grid>
<ScrollViewer>
<skia:SKElement Name="DrawCanvas" PaintSurface="SKElement_PaintSurface">
</ScrollViewer>
</Grid>
</UserControl>
private void SKElement_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
\\Code goes here...
DrawCanvas.Height = 100;
}

How to zoom at center in scroll viewer while using ZoomToFactor to increase zoom level in button click

I am using scroll viewer to zoom the image which is set as background for Grid.When, I am setting the zoom factor value on button click from code behind with scrollViewer.ZoomToFactor(zoomFactor) image is getting zoomed from Top left corner ,not from the center position.
Please get the sample from the below link or below code snippet for your reference.
Link: https://github.com/ragulsv/ScrollViewer
Code Snippet[C#]:
float count = 1;
private void Clr_Click(object sender, RoutedEventArgs e)
{
count = 1;
viewer.ZoomToFactor(count);
viewer.RenderTransformOrigin = new Point(0.5, 0.5);
}
private void Btn_Click(object sender, RoutedEventArgs e)
{
viewer.ZoomToFactor(count);
viewer.RenderTransformOrigin = new Point(0.5, 0.5);
count += 1;
}
Code Snippet[Xaml]:
<Grid x:Name="grid1">
<Grid.RowDefinitions>
<RowDefinition Height="0.1*">
</RowDefinition>
<RowDefinition Height="0.1*">
</RowDefinition>
<RowDefinition Height="0.8*">
</RowDefinition>
</Grid.RowDefinitions>
<Button x:Name="btn" Grid.Row="0"></Button>
<Button x:Name="clr" Grid.Row="1"></Button>
<ScrollViewer x:Name="viewer" Grid.Row="2" ZoomMode="Enabled">
<Grid>
<Image Source="Assets\EditedImage.jpg" Height="190" Width="190"/>
</Grid>
</ScrollViewer>
</Grid>
How to zoom at center in scroll viewer while using ZoomToFactor to increase zoom level in button click
For this scenario, you could set Image's parent Grid VerticalAlignment="Center" HorizontalAlignment="Center" that could make the image always fix on the center of ScrollViewer and then call ChangeView method to edit ZoomFactor.
private void Btn_Click(object sender, RoutedEventArgs e)
{
viewer.ChangeView(0, 0, (viewer.ZoomFactor + 1f));
}

Enlarge image after click C# UWP

How can I enlarge image in C# (exactly in UWP) after clicking on it?
I tried few things:
1) I tried to add button, with image content, what I want to enlarge, and then I added event Click. But I don't know what I should to add into that code.
2) i also tried to add image directly to my XAML page, and I wanted to create Tapped event, but again, I don't know what I should to add into that code.
I just want to create a small photogallery, so after clicking on image thumbnail will be opened larger image.
Or if there is any possibility to add pdf files, you can write it too. That's another solution of my problem.
You could enlarge the Image by settings its RenderTransform property to a ScaleTransform:
private void Image_Tapped(object sender, TappedRoutedEventArgs e)
{
Image image = sender as Image;
image.RenderTransform = new ScaleTransform() { ScaleX = 2, ScaleY = 2 };
}
<Image Source="ms-appx:///Assets/pic.png" Tapped="Image_Tapped" Stretch="None" />
The ScaleX and ScaleY properties gets or sets the scaling factor. Please refer to the MSDN documentation for more information: https://msdn.microsoft.com/library/windows/apps/br242940?f=255&MSPPError=-2147217396
Looks good, but there is a problem. When I add more images, like into GridView, they are overlapping, and highlighted. Images can overlap, but image, which I click should be always on top...
You could put the tapped Image in a Popup then and then for example add it back to its original Panel when it is tapped again. I put together an example that should give you the idea and something to build on:
private void Image_Tapped(object sender, TappedRoutedEventArgs e)
{
Image image = sender as Image;
Panel parent = image.Parent as Panel;
if (parent != null)
{
image.RenderTransform = new ScaleTransform() { ScaleX = 2, ScaleY = 2 };
parent.Children.Remove(image);
parent.Children.Add(new Popup() { Child = image, IsOpen = true, Tag = parent });
}
else
{
Popup popup = image.Parent as Popup;
popup.Child = null;
Panel panel = popup.Tag as Panel;
image.RenderTransform = null;
panel.Children.Add(image);
}
}
<GridView SelectionMode="None" isItemClickEnabled="True">
<GridView.ItemTemplate>
<DataTemplate>
<Grid>
<Image Source="ms-appx:///Assets/pic.png" Tapped="Image_Tapped" Stretch="None" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>

WPF Expander - when GridSplitter used to manually resize row, row does not properly collapse

This is what I have
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="25"/>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Expander IsExpanded="False" Grid.Row="0" >
<DataGrid name="FirstGrid" />
</Expander>
<GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" Height="5" />
<DataGrid Grid.Row="2" name="SecondGrid" />
When I click the expand button on the expander it correctly expands row 0 to the size of the DataGrid FirstGrid and it properly collapses the row as well. This does not work however if I expand the FirstGrid then manually resize that row by dragging the GridSplitter up or down and then pressing collapse button on the expander. What happens is that FirstGrid collapses but the row itself the FirstGrid is in does not. Any suggestions?
Thanks
Rob is right, once you move the gridsplitter, the Height of the first Row will not be Auto anymore, so it will not respond to the change in the expander size
In order for this to work you would need to add a behavior to the expander which will listen to the expander.expanded and collapsed event and update the grid row to be auto again. something like this:
public class GridColumnWidthReseterBehaviour : Behavior<Expander>
{
private Grid _parentGrid;
public int TargetGridRowIndex { get; set; }
protected override void OnAttached()
{
AssociatedObject.Expanded += AssociatedObject_Expanded;
AssociatedObject.Collapsed += AssociatedObject_Collapsed;
FindParentGrid();
}
private void FindParentGrid()
{
DependencyObject parent = LogicalTreeHelper.GetParent(AssociatedObject);
while (parent != null)
{
if (parent is Grid)
{
_parentGrid = parent as Grid;
return;
}
parent = LogicalTreeHelper.GetParent(AssociatedObject);
}
}
void AssociatedObject_Collapsed(object sender, System.Windows.RoutedEventArgs e)
{
_parentGrid.RowDefinitions[TargetGridRowIndex].Height= GridLength.Auto;
}
void AssociatedObject_Expanded(object sender, System.Windows.RoutedEventArgs e)
{
_parentGrid.RowDefinitions[TargetGridRowIndex].Height= GridLength.Auto;
}
}
And you use it like this:
<Expander ...>
<interactivity:Interaction.Behaviors>
<behaviors:GridColumnWidthReseterBehaviour TargetGridRowIndex="0"></behaviors:GridColumnWidthReseterBehaviour>
</interactivity:Interaction.Behaviors>
...
As soon as you move the gridsplitter, the Height of the first Row will not be Auto anymore, but a certain value, like 70. After that it doesn't matter if some child in that row changes its height.
Combining a splitter with some auto-sized child/row is very difficult; you can take a look at the side expander in Microsoft Outlook; i suspect that this is what you want. If so, you shouldn't use an expander, because a regular expander contains a StackPanel so its children are always auto-sizing in the expand direction. I'm not sure what you want, but i think going for a custom control is your best option.

Categories

Resources