WPF: Opacity and the MouseEnter Event - c#

As part of a diagram, I am drawing a few overlapping Shapes, each with Opacity=0.5, like here:
<Grid>
<Rectangle Fill="Blue" Opacity="0.5" MouseEnter="Rectangle_MouseEnter" />
<Rectangle Fill="Red" Opacity="0.5" />
</Grid>
private void Rectangle_MouseEnter(object sender, MouseEventArgs e)
{
MessageBox.Show("Entered");
}
When the user enters the shape with the mouse, some additional information should be displayed, but the event handler never gets called.
Is there a way to get MouseEnter events for all Shapes, instead of just the topmost one?

With your layout only the topmost rectangle will raise MouseEnter event. It fully overlaps the first rectangle.
Try this code for eventHandler:
private void Rectangle_MouseEnter(object sender, MouseEventArgs e)
{
if (sender != grid.Children[0])
{
var rect = (grid.Children[0] as Rectangle);
if (rect != null) rect.RaiseEvent(e);
}
else
{
MessageBox.Show("Entered.");
}
}
For this works you need to subscribe both rectangles to Rectangle_MouseEnter.

Related

WPF Canvas Panning and Zoom

I've created an application that can read an XML file and display the rail network specified within a WPF Canvas.
I've been struggling for a while (months) to get the following functionality working and looking for any clue on how to proceed:
Zoom using mousewheel (zooming in makes the icons and tracks bigger whilst zooming out can let me see all the network).
Panning - Using the middle mouse button to drag the view screen.
I ended up having to disable the mouse wheel as it just moved the scrollviewer. In order for me to scroll currently, I have to use the scrollbar arrows.
Usually I would upload code samples but I've also uploaded everything to GitHub with everything needed in case you need to dive into the code or compile.
https://github.com/Legolash2o/NMViewer
XAML
<ScrollViewer x:Name="svCanvas" Grid.Row="2" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" MouseMove="CCanvas_OnMouseMove" PreviewMouseWheel="SvCanvas_OnPreviewMouseWheel" MouseWheel="SvCanvas_OnPreviewMouseWheel" MouseDown="SvCanvas_OnMouseDown">
<Canvas x:Name="cMain" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Width="36000" Height="58000" >
<Canvas.RenderTransform>
<ScaleTransform x:Name="st"/>
</Canvas.RenderTransform>
</Canvas>
</ScrollViewer>
C#
private void SvCanvas_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
}
private void SvCanvas_OnMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.MiddleButton == MouseButtonState.Pressed)
{
st.ScaleX = 1;
st.ScaleY = 1;
}
}
private void CCanvas_OnMouseMove(object sender, MouseEventArgs e)
{
if (drawing)
return;
lblBar.Content =
$"H[{svCanvas.HorizontalOffset}, V{svCanvas.VerticalOffset}] Mouse: {Mouse.GetPosition(cMain)}";
}

WPF: Focus border after click

I'm trying to get my border focused after the user clicks on it.
Currently it is possible to focus the border via tabs, but via click would be way more convenient for the user.
<Border x:Name="BorderFileInfo" Focusable="True" BorderBrush="LightGray" BorderThickness="1">
<Grid Margin="3,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left">
<!-- CONTENT CTRL -->
</Grid>
</Border>
I saw in another post that there is a possability to catch the click event with an InputBinding but I don't know how to focus the border afterwards without using a command.
Stackoverflow: Why doesnt WPF border control have a mousedoubleclick event?
Is there an easy way to do that other than having to create commands ?
The app is pretty small so I don't want to use commands if I don't have to.
One easy way is to handle PreviewMouseDown or similar mouse events and set the focus:
private void Border_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Keyboard.Focus(sender as Border);
}
edit
note that you can create Click by handling PreviewMouseLeftButtonDown and PreviewMouseLeftButtonUp in this way:
_isdown =false;
private void Border_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_isdown =true;
}
private void Border_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if ( _isdown)
{
_isdown = false;
Keyboard.Focus(sender as Border);
}
}

Creating UI element when user clicks in wpf

What I want to do is make it so when the user clicks the 'rectangle' shape it creates a white border around the box like so....
If the user clicks in an area where no rectangle is present then it deselects any selected rectangles. I'm assuming this may need some additional changes in the code, any suggestions are welcome!
I found a solution for you. Let me know if this works for you. If not I will try and modify it. It is basic, but not that hard to implement I believe.
Here is the XAML. Note you will have to do all the positioning of the rectangles and such yourself. This just selects and deselects with a black border.
<Grid Background="#00000000" MouseDown="Grid_MouseDown" >
<Border Visibility="Hidden" x:Name="border" BorderBrush="Black" BorderThickness="1" Margin="230,135,142,58">
</Border>
<Rectangle x:Name="rect" Fill="Blue" MouseDown="Rectangle_MouseDown" Margin="250,148,160,74"/>
</Grid>
And here is the code behind.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Rectangle_MouseDown(object sender, MouseButtonEventArgs e)
{
border.Visibility = Visibility.Visible;
}
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.MouseDevice.DirectlyOver == rect)
{
}
else
{
border.Visibility = Visibility.Hidden;
}
}
}

Moving Image in ScrollViewer (UWP)

I've got a Image in Scrollviewer...
<ScrollViewer x:Name="Scrollster" ZoomMode="Enabled" MinZoomFactor="1" MaxZoomFactor="4"
HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" ManipulationMode="All">
<Image x:Name="Img" Source="{x:Bind ImgSource}" Stretch="UniformToFill" PointerPressed="Img_PointerPressed"/>
</ScrollViewer>
I want to move Image when I drag image with Mouse Pointer!
I tried:
private void Img_PointerPressed(object sender,PointerRoutedEventArgs e)
{
var p = e.Pointer;
}
but I can't get pointer position to change scrollviewer postion.
What's wrong with my code? Am I doing it right?
The ManipulationMode should be set on the Img control instead. Also, you probably want to specify the exact modes you want rather than All to prevent unnecessary gesture handling.
<Image x:Name="Img" Source="{x:Bind ImgSource}" Width="150" Height="150" Stretch="UniformToFill"
ManipulationMode="TranslateX, TranslateY"
ManipulationStarted="Img_ManipulationStarted"
ManipulationDelta="Img_ManipulationDelta"
ManipulationCompleted="Img_ManipulationCompleted">
<Image.RenderTransform>
<CompositeTransform x:Name="Transform" />
</Image.RenderTransform>
</Image>
From your description above, I think turning on both TranslateX and TranslateY should be sufficient. Then you will need to handle manipulation events like ManipulationStarted, ManipulationDelta and ManipulationCompleted.
Most of your logic should be done in ManipulationDelta event which will be fired multiple times during the progression of the panning. It's where you get the X and Y positions and set them accordingly.
Here is a simple sample for this.
void Img_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
// dim the image while panning
this.Img.Opacity = 0.4;
}
void Img_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
this.Transform.TranslateX += e.Delta.Translation.X;
this.Transform.TranslateY += e.Delta.Translation.Y;
}
void Img_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
// reset the Opacity
this.Img.Opacity = 1;
}

How to change the location of wpf grid at run time?

I have created a WPF Grid. That grid contains Textbox and Button controls.Here i want to relocate the grid at run time .How its possible please answer this if you know.Like a movable window.
I don't know if you want to relocate after mouse events or in code after some different event? If second you can change grid margins in event/method where you want to do it and call UpdateLayout() method after it. If first here is my answer for similar question:
Check time after a mousebuttondown before the mousebuttonup
I found this solution on stackoveflow
<Grid x:Name="grid" Background="Blue"
Width="100" Height="100"
MouseDown="Grid_MouseDown" MouseMove="Grid_MouseMove" MouseUp="Grid_MouseUp">
<Grid.RenderTransform>
<TranslateTransform x:Name="tt"/>
</Grid.RenderTransform>
Place it in a window
<Window x:Name="window" ...>
<Grid x:Name="grid"...
And code:
Point m_start;
Vector m_startOffset;
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
m_start = e.GetPosition(window);
m_startOffset = new Vector(tt.X, tt.Y);
grid.CaptureMouse();
}
private void Grid_MouseMove(object sender, MouseEventArgs e)
{
if (grid.IsMouseCaptured)
{
Vector offset = Point.Subtract(e.GetPosition(window), m_start);
tt.X = m_startOffset.X + offset.X;
tt.Y = m_startOffset.Y + offset.Y;
}
}
private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
{
grid.ReleaseMouseCapture();
}

Categories