The question is pretty simple: How do I prevent LostFocus from getting raised on MouseDown on a control that already got focus?
I have the following control (temporary test with all the event bindings):
<Grid Name="gBase" Focusable="True" MouseUp="SetFocus" MouseDown="SetFocus" MouseMove="gBase_MouseMove" PreviewDragEnter="gBase_PreviewDragEnter" LostFocus="gBase_LostFocus" GotFocus="gBase_GotFocus" Background="DarkRed" Width="500" Height="250" />
And the following code behind:
private void SetFocus(object sender, MouseButtonEventArgs e)
{
Grid g = sender as Grid;
g.Focus();
}
private void gBase_LostFocus(object sender, RoutedEventArgs e)
{
Grid g = sender as Grid;
g.Background = Brushes.DarkRed;
}
private void gBase_GotFocus(object sender, RoutedEventArgs e)
{
Grid g = sender as Grid;
g.Background = Brushes.Aquamarine;
}
private void gBase_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Grid g = sender as Grid;
g.Focus();
}
}
private void gBase_PreviewDragEnter(object sender, DragEventArgs e)
{
Grid g = sender as Grid;
g.Focus();
}
The behaviour is almost of that I want to achieve, if I click on the Grid it get focus.
The problem is that if the Grid already got focus it will lose it while I have the mouse button down and not regain it until I release or move. My prefered behaviour would be to prevent that it loses focus in the first place.
The problem was that the parent ScrollViewer stole focus.
This was solved by using the event MouseLeftButtonDown and setting the MouseButtonEventArgs.Handled to true to prevent further handling of the event.
Working code:
<Grid Name="gBase" Focusable="True" MouseLeftButtonDown="SetFocus" LostFocus="gBase_LostFocus" GotFocus="gBase_GotFocus" Background="DarkRed" MinWidth="500" MinHeight="250" Width="500" Height="250" HorizontalAlignment="Left" />
private void SetFocus(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
Grid g = sender as Grid;
g.Focus();
}
Use some property or variable to store which control has actually focus. And after MouseDown compare if control already had focus and if so, then don't do code in LostFocus event.
Important is to update storing property, when focus is changed on other control.
Related
I have Windows Form named Form1 and inside I have a dynamic SplitContainer named splitcontainer.
I want to know which panel is selected when the mouse is clicked at runtime.
I tried to use mouseclick event in the splitContainer properties but I haven't succeed.
You need to bind to the MouseClick events of the panel inside the split container.
I added a container called "splitContainer1" with 2 panels, Panel1 and 2
I wired up the below events and it seems to work
private void splitContainer1_Panel1_MouseClick(object sender, MouseEventArgs e)
{
MessageBox.Show("Panel1");
}
private void splitContainer1_Panel2_MouseClick(object sender, MouseEventArgs e)
{
MessageBox.Show("Panel2");
}
After your further comments, I've edited the below to show how to manually bind the mouse click events of the 2 panels of your dynamically added container.
private void splitContainerHorizontalToolStripMenuItem_Click(object sender, EventArgs e)
{
SplitContainer spltcnt = new SplitContainer();
spltcnt.Dock = DockStyle.Left;
spltcnt.Orientation = Orientation.Horizontal;
spltcnt.SplitterWidth = 4;
spltcnt.Visible = true;
spltcnt.Size = new System.Drawing.Size(731, 615);
spltcnt.BorderStyle = BorderStyle.Fixed3D;
spltcnt.SplitterDistance = 351;
//Manually bind the mouse click events.
spltcnt.Panel1.MouseClick += Panel1OnMouseClick;
spltcnt.Panel2.MouseClick += Panel2OnMouseClick;
Controls.Add(spltcnt);
}
private void Panel1OnMouseClick(object sender, MouseEventArgs mouseEventArgs)
{
MessageBox.Show("Panel1");
}
private void Panel2OnMouseClick(object sender, MouseEventArgs mouseEventArgs)
{
MessageBox.Show("Panel2");
}
You can of course call the mouse click handler methods anything you like.
Thanks
After I touch a control, such as Button, How can I get this button's name?
If you mean "click" instead of "touch", put something like this in your View XAML file:
<Button x:Name="MyButton" MouseDown="MyButton_MouseDown">
Then add following lines to the View CODE file:
void MyButton_MouseDown(object sender, MouseButtonEventArgs e) {
base.OnMouseUp(e);
var control = sender as FrameworkElement;
Console.WriteLine(control.Name);
}
When you click on a control you are raising an event which called : Control_Click
Then you can do whatever you want in that even. As you asked about button I'm gonna show you how you can get button's name . You can have the similar code for other controls :
private void button1_Click(object sender, EventArgs e)
{
string control_name = button1.Name;
MessageBox.Show(control_name);
}
If a textbox has focus and I want to be able to select it again is there a way to do this.
So first click the background turns blue and while it is still selected I press again the background turns green. How do I catch the second press even though its already selected?
You can subscribe to the PointerEntered and the SelectionChanged events. The first one is always fired when the pointer hits the TextBox. However if it contains text and you tap on it you will eventually select the text. The SelectionChanged handler will take care for that.
Your XAML markup looks as follows:
<TextBox x:Name="tb"
Text="Test"
PointerEntered="TextBox_PointerEntered"
SelectionChanged="TextBox_SelectionChanged"
GotFocus="TextBox_GotFocus"/>
The code behind file contains the following code:
private void TextBox_PointerEntered(object sender, PointerRoutedEventArgs e)
{
tb.Background = new SolidColorBrush(Colors.Green);
}
private void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
{
tb.Background = new SolidColorBrush(Colors.Green);
}
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
tb.Background = new SolidColorBrush(Colors.Blue);
}
You will have to adjust the code to your needs and take care of special cases where both SelectionChanged AND PointerEntered are fired (at this point both handlers do the same, so there's no problem).
In my WPF application I have Toggle Button, I want to detect when user double click on it (in both cases if it checked or unchecked).
How can I do that?
Thanks in advance
You can use the OnPreviewMouseDoubleClick event
xaml:
<ToggleButton Height="75" Width="100" PreviewMouseDoubleClick="Control_OnPreviewMouseDoubleClick"/>
code-behind:
private void Control_OnPreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
var toggleButtton = sender as ToggleButton;
if (toggleButtton != null)
{
if (toggleButtton.IsChecked.HasValue)
{
if (toggleButtton.IsChecked.Value)
{
// Checked
}
else
{
// Unchecked
// this will re-check the button if double-click unchecks it
//
toggleButtton.IsChecked = true;
toggleButtton.Focus();
}
}
}
}
Use PreviewMouseDoubleClick event (msdn):
XAML:
<ToggleButton x:Name="tButton" Height="30" Content="MyButton"
PreviewMouseDoubleClick="tButton_PreviewMouseDoubleClick"
/>
Code-behind:
private void tButton_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
tButton.IsChecked = !tButton.IsChecked.Value;
e.Handled = true;
//...
}
This event is pretty easy with togglebuttons
Xaml you write the following to get an EventHandler:
<ToggleButton Name="button1" MouseDoubleClick="button1_DoubleClick" />
In c# you write the following to get an EventHandler:
button1.MouseDoubleClick += new MouseButtonEventHandler(button1_DoubleClick);
And in both cases you need:
void button1_DoubleClick(object sender, MouseButtonEventArgs e)
{
}
In the WPF TabControl the default behavior is to change the selected tab on mouse down.
In my application changing the tab sometimes resizes things, and at times the mouse up event will get called on a another user control because the tabcontrol moved.
If i can set the tab pages to switch only on mouse up rather than mouse down it would solve the issue.
You can use a custom TabItem like so:
public class MyTabItem : TabItem {
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
if (e.Source == this || !this.IsSelected)
return;
base.OnMouseLeftButtonDown(e);
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) {
if (e.Source == this || !this.IsSelected)
base.OnMouseLeftButtonDown(e); // OR just this.Focus(); OR this.IsSeleded = true;
base.OnMouseLeftButtonUp(e);
}
}
You can subscribe to the PreviewMouseDown event and set the Handled flag of the routed event to disable the mousedown, and then on MouseUp you can set IsSelected on the TabItem. This way you don't have to create custom control.
XAML
<TabItem Header="My Tab" MouseUp="TabItem_MouseUp" PreviewMouseDown="TabItem_PreviewMouseDown">
<!--Content-->
</TabItem>
C#
private void TabItem_MouseUp(object sender, MouseButtonEventArgs e)
{
if (sender is TabItem tab && !tab.IsSelected)
tab.IsSelected = true;
}//end private void TabItem_MouseUp(object sender, MouseButtonEventArgs e)
private void TabItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (sender is TabItem tab && !tab.IsSelected)
e.Handled = true;
}//end private void TabItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)