WPF: Focus border after click - c#

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);
}
}

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)}";
}

How do I make a tooltip displayw hen mouse cursor is over button in WPF

How can I make a tooltip appear when a button is hovered over with the mouse in WPF?
Try this:
<Button ToolTipService.InitialShowDelay="5000"
ToolTipService.ShowDuration="2000"
ToolTipService.BetweenShowDelay="10000"
ToolTip="This is a tool tip." />
"ToolTip" is the property that needs to be set for adding text to controls that are actively being hovered over.
You can create 2 events: PointerEntered and PointerExited, draw content for button and give a name to content (or to it's template)
Xaml:
<Button PointerEntered="Button_PointerEntered" PointerExited="Button_PointerExited" >
<Button.Content>
<TextBlock x:Name="txtBlock1" Text="not hovering" />
</Button.Content>
</Button>
on code behind you handle those events:
private void Button_PointerEntered(object sender, PointerRoutedEventArgs e)
{
txtBlock1.Text = "hovering";
}
private void Button_PointerExited(object sender, PointerRoutedEventArgs e)
{
txtBlock1.Text = "not hovering";
}

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();
}

How to invalidate Forms control continously without interfere with WPF?

I have a Control that is in a WindowsFormsHost. This control is for drawing content in an OpenGL context and need to be invalidated after every draw.
The problem: WPF Controls are not reacting anymore, if I do that. You can click on them and they work, but you do not get any visual feedback like when you hover over it or press the WPF button. The button does not change the color or something it normaly does, if you hover over it.
I created a little repro for you:
XAML
<Grid>
<WindowsFormsHost x:Name="uxContainerWindowsFormsHost" HorizontalAlignment="Left" Height="163" Margin="101,29,0,0" VerticalAlignment="Top" Width="223"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="225,260,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
Code
public MainWindow()
{
InitializeComponent();
var b = new System.Windows.Forms.Button();
b.BackColor = System.Drawing.Color.Gray;
b.Text = "Button";
b.Paint += b_Paint;
uxContainerWindowsFormsHost.Child = b;
}
void b_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
(sender as System.Windows.Forms.Button).Invalidate();
}
If you click on the WPF button, you will not get any visual feedback that you clicked on the button.
Question
How can I use a continous invalidation in my WindowsFormsHost like in the repro, without loosing the visual feedback on my buttons?
The solution was the CompositionTarget.Rendering event that Dr. ABT showed in the comment.
Constructor()
{
CompositionTarget.Rendering += CompositionTarget_Rendering;
}
void CompositionTarget_Rendering(object sender, EventArgs e)
{
_myControl.Invalidate();
}

WPF: Opacity and the MouseEnter Event

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.

Categories