On my window, there is a textbox, a combobox and a TextBlock.
Now I click the textbox to focus on it.
I want to monitor the event: when click other controls (the combobox, the TextBlock, even the empty area on the window) besides this textbox.
Are there any events that can handle it directly? Rather than binding mouseevent for each control.
You could handle the tunneling PreviewMouseLeftButtonDown of the parent window:
public MainWindow()
{
InitializeComponent();
PreviewMouseLeftButtonDown += (s, e) =>
{
if (e.Source != theTextBox)
{
MessageBox.Show("Click detected outside the TextBox!");
}
};
}
Related
I'm experimenting the OnPreviewMouseUp and OnPreviewMouseDown tunneling events. I'm particularly interested in e.OriginalSource as I don't understand why when I click on the text content of the button, e.OriginalSource is still the button itself, and not the text block - the visual child of the button. In fact I found the OnPreviewMouseDown event does do what I expected -- it shows e.OriginalSource as text block, however the OnPreviewMouseUp event always shows e.OriginalSource as the button itself. The following is the simple code I used for this experiment:
XAML:
<StackPanel Margin="5">
<Button Name="cmd" Margin="8">Click me.</Button>
</StackPanel>
Code behind:
public partial class ButtonMouseUpEvent : System.Windows.Window
{
public ButtonMouseUpEvent()
{
InitializeComponent();
}
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
{
base.OnPreviewMouseDown(e);
Debug.WriteLine($"OnPreviewMouseDown(): e.Source = {e.Source}, e.OriginalSource = {e.OriginalSource}");
}
protected override void OnPreviewMouseUp(MouseButtonEventArgs e)
{
base.OnPreviewMouseUp(e);
Debug.WriteLine($"OnPreviewMouseUp(): e.Source = {e.Source}, e.OriginalSource = {e.OriginalSource}");
}
I suspect this has something to do with button's click event, which eats up the MouseUp event, but I'm trying to understand exactly why.
I have a usercontrol ROOT_CONTROL that contains another user control SUB_CONTROL , which contains button BUTTON.
ROOT_CONTROL- > SUB -> BUTTON
<UserControl x:Name="ROOT_CONTROL"
GotKeyboardFocus="UserControl_GotKeyboardFocus">
<StackPanel>
<UserControl x:Name="SUB_CONTROL">
<Button x:Name="BUTTON" Click="BUTTON_Click">
</UserControl>
</StackPanel>
<SUB_Control>
</UserControl>
I have a UserControl_GotKeyboardFocus eventhandler connected with ROOT_CONTROL, I have an Button_Click eventhandler connected with BUTTON. When user clicks on BUTTON and there is a KeyboardFocus on that ROOT_CONTROL - it works ok, but when there is no KeyboardFocus on that control (or any of its children) it fires UserControl_GotKeyboardFocus (and that's ok), but then it does not fire BUTTON click event.
So when there is no keyboard focus on that control, user needs to click twice to see result (once to give focus, second to fire button event).
I do not change property e.Handled to true inside UserControl_GotKeyboardFocus eventhandler.
How to easily (if it is possible) fire BUTTON click eventhandler when there is no keyboardfocus on ROOT_CONTROL?
EDIT:
private void UserControl_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (Guard)
{
Guard = false;
}
else
{
if (e.OldFocus == null)
{
if (SessionData.SelectionWindow != null && !(SessionData.SelectionWindow.Visibility == Visibility.Visible))
{
SessionData.SelectionWindow.Ano.UpdateSelection();
SessionData.SelectionWindow.UpdatePosition();
SessionData.SelectionWindow.Visibility = Visibility.Visible;
if (e.OriginalSource is FrameworkElement)
{
(e.OriginalSource as FrameworkElement).Focus();
}
}
else
{
}
}
else
{
}
}
}
I created a UserControl like Popup which is displayed when user clicks on menu item.
If user clicks side that user control should be collapsed.
It works fine for me when user clicks side other than any control.
If I click on datagrid or listbox it is not hiding.
Here is my code:
<src:AddNewItemPopUp x:Name="PopUp" Margin="111,47,620,230" Panel.ZIndex="1" Visibility="Collapsed"/>
I took a button in click event I set PopUp visibility property to true
In my user control I have grid. In the mousedown event of grid I have written following code...
private void Grid_MouseDown_1(object sender, MouseButtonEventArgs e)
{
if (PopUp.Visibility == Visibility.Visible)
{
PopUp.Visibility = Visibility.Collapsed;
}
}
If I click on any control like a Button, DataGrid, ListBox that are placed in Grid Popup is not collapsed.
First Set Grid's Background Property, for example grid.Backgroung=Brushes.Transparent or in Xaml Backgroung = "Transparent"
Second Handle PreviewMouseDown event instead of MouseDown event.
The first one makes the mouse event to fire, when mouse is directly over the grid.
The second one makes the mouse event fire, when mouse is over an UIElement in the grid.
Try:
Visibility="Hidden"
that is:
private void Grid_MouseDown_1(object sender, MouseButtonEventArgs e)
{
if (PopUp.Visibility == Visibility.Visible)
{
PopUp.Visibility = Visibility.Hidden;
}
}
and also see:
http://msdn.microsoft.com/en-us/library/system.windows.visibility.aspx
How can i disable a button until an item is selected in a listbox?
Initially you disable your button:
button1.Enabled = false;
Then you subscribe to the SelectedIndexChanged event of the listbox. Bellow is the handler:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listBox1.SelectedIndex >= 0)
{
button1.Enabled = true;
}
else
{
button1.Enabled = false;
}
}
You subscribe to the event from the Visual Studio IDE, or programatically like this:
listBox1.SelectedIndexChanged+=new EventHandler(listBox1_SelectedIndexChanged);
Since you mention winforms, one way is to set the property of the button IsEnabled=false in the property explorer. Then add an event for the listbox OnSelectionChanged. VS will automatically insert the code behind for you, then you can put this in the event handler:
button1.IsEnabled = listbox1.SelectedIndex > 0;
If you are using WPF you can do it the same way, but it would be better to use Databinding.
I've got an issue with a custom control that I've written not firing it's ContextMenuOpening event when I hook it up programatically. The control is basically a wrapper for the standard TextBox:
public class MyTextBox : TextBox
{
public MyTextBox()
{
this.ContextMenuOpening += new ContextMenuEventHandler(MyTextBox_ContextMenuOpening);
}
void MyTextBox_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
MessageBox.Show("ContextMenuOpening event fired");
}
}
There's nothing suspect either about the XAML:
<local:MyTextBox Height="25" Width="300"/>
For some reason though, I can never get the event to fire. I'm trying to intercept the context menu so I can alter it (it's context sensitive) and really am trying to avoid having to hook up the event everywhere the control is used - surely this is possible?
Turns out you need to explicity set the ContextMenu to null when creating the object:
public MyTextBox()
{
this.ContextMenu = null;
this.Initialized += (s, e) =>
ContextMenuOpening += new ContextMenuEventHandler(MyTextBox_ContextMenuOpening);
}
Then it works a treat :)
The ContextMenuOpening-Event will only be fired after you assign a new context menu to the property ContextMenu:
public MyTextBox()
{
this.ContextMenu = new ContextMenu();
this.ContextMenu.Items.Add(new MenuItem {Header = "Do stuff"});
...
}