Who handled my event - c#

I have registered to a LostFocus event on a TextBox and yet the event is not catch - my guess is that someone else handled it.
I've tried using snoop but it only shows me the MouseDown and MouseUp events (and I need the LostFocus).
Any ideas on how can I find out?
Thanks
Update:
Not so clear but the code where I register is:
eventInfo.AddEventHandler(cloningObject, eventDelegate);

In the XAML, make sure you assign a name to your TextBox:
<TextBox Name="MyTextBox" />
Create a function in your code behind to handle the event:
public void MyLostFocusHandler(object sender, RoutedEventArgs e) {
// ...
}
And then in your window's constructor (assuming this is in a window):
MyTextBox.LostFocus += MyLostFocusHandler;
Note also there is another event, LostKeyboardFocus.

Related

Hyperlink events are not raised on first click if MousePreviewUp event is subscribed

I have loaded a TextBlock in a ContentControl and added a Hyperlink as an object in the Inlines collection in the TextBlock.
If I subscribe a handler to the ContentControl.PreviewMouseUp event which sets the ContentControl.Foreground property, the RequestNavigate and Click events are not raised the first time the link is clicked. If the link is clicked a second time, the events are raised.
Everything works fine if the event is not subscribed, or the handler does nothing.
Initialization code (in window constructor, after InitializeComponent()):
var run = new Run("Google");
Hyperlink hyperlink = new Hyperlink(run);
hyperlink.Click += hyperlink_Click;
hyperlink.RequestNavigate += hyper_RequestNavigate;
hyperlink.NavigateUri = new Uri("http://www.google.com");
textBlock.Inlines.Clear();
textBlock.Inlines.Add(hyperlink);
Event handlers as follows:
private void hyper_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
System.Diagnostics.Process.Start(e.Uri.ToString());
}
void contentControl_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
contentControl.Foreground = Brushes.Green;
}
void hyperlink_Click(object sender, RoutedEventArgs e)
{
}
XAML as follows:
<Grid>
<ContentControl Name="contentControl">
<TextBlock Name="textBlock"
Width="200"
Height="30" />
</ContentControl>
</Grid>
Note: if the PreviewMouseUp handler is changed so that it always changes the color (e.g. create a bool that selects between two different colors and is toggled each time the handler is called), the events are never raised. E.g.:
private bool _toggle;
void contentControl_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
contentControl.Foreground = _toggle ? Brushes.Red : Brushes.Green;
_toggle = !_toggle;
}
Is there any way to have the PreviewMouseUp handler set the color but still have the RequestNavigate and Click events raised when the link is clicked the first time?
I don't know exactly what's going on here, but it's clear from the symptoms that there's something about changing the ContentControl.Foreground property that interrupts the normal handling of the mouse event. When you set the property value, this causes WPF to decide that the event should be ignore (maybe it treats the property change as an indication that the event has been handled), and so the events which would normally be raised later aren't in fact raised.
Given that, it seems to me that the most obvious work-around is to defer the change in the property value until after mouse event has in fact been completely handled, including raising those events. And the most obvious way I can think of to do that is to use the Dispatcher to invoke the operation later.
I.e. by using Dispatcher.InvokeAsync(), we can ensure that the handling of the mouse event itself is completely processed before the property change is done, because the dispatcher is busy dealing with the mouse event and won't be available to run the invoked delegate until it's finished with the mouse event.
That would look something like this:
void contentControl_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
Dispatcher.InvokeAsync(() =>
{
contentControl.Foreground = Brushes.Green;
});
}
If you change your PreviewMouseUp handler to the above, you should see that the events are raised even on the first mouse click.

How to register event for TextBox end editing

Super newbie to C# (first day coding), so please don't judge me too much if the following is really a stupid question to you.
But I am looking for a way to register an event for when a TextBox end editing, which is similar textFieldDidEndEditing(_ textField: UITextField) delegate in iOS.
After some googling around, I know how to register an textChanged event with the following:
In .xaml file:
<TextBox TextChanged="textChangedEventHandler"/>
In .cs file:
protected void textChangedEventHandler(object sender, TextChangedEventArgs args)
{
}
I also notice this SO, and finally this documentation by MS and notice this following function:
// This method handles the LostFocus event for textBox1 by setting the
// dialog's InitialDirectory property to the text in textBox1.
private void textBox1_LostFocus(object sender, System.EventArgs e)
{
// ...
}
But what is not obvious to me is how do I register this event function? Or how do I let the GUI know to call this function when the TextBox end editing?
This is finally what it takes for it to work:
In .xaml file:
<TextBox LostFocus="textFinishedEditingEventHandler"/>
In .cs file:
public void textFinishedEditingEventHandler(object sender, RoutedEventArgs e)
{
}
Thanks to #Dacker!~
Normally an event can be registered in two ways:
In markup. In ASP.Net each type of event is exposed with the prefix On, so for Click it's OnClick. In your xaml I don't see the On prefix, so that makes me guess it is the following in your case:
<TextBox LostFocus="textBox1_LostFocus" />
In code behind (.cs)
textBox1.LostFocus += textBox1_LostFocus
If you understand this, you can use better names for textBox1_LostFocus to describe more what will happen instead of when it will happen.

Can anyone raise any RoutedEvent in WPF?

In C# events were always very protected: Only the owner of the event could trigger them. However, this seems to be completely different in WPF - Anyone can throw any event at any time. To test that, I've written the code in the bottom.
When I used RaiseEvent to raise Button.Click, the event above caught it. Is that the planned behavior of WPF events? Just letting anyone throw any events they wish? Also, if so, then what is the meaning of the OwnerType when you register the event? I thought it is some kind of protection, yet if it is, it is a poor one since anyone can access the public event and use AddOwner function to add more owners.
Thanks!
XAML
<StackPanel Button.Click="ButtonBase_OnClick">
<Button Name="RealButton">Real button</Button>
<WpfWindow:VitalyControl MouseDown="UIElement_OnMouseDown">
I am almost a button
</WpfWindow:VitalyControl>
</StackPanel>
Code behind
The custom control:
class VitalyControl : Label
{
public VitalyControl()
{
this.MouseDown += new MouseButtonEventHandler(VitalyControl_MouseDown);
}
void VitalyControl_MouseDown(object sender, MouseButtonEventArgs e)
{
RaiseEvent(new RoutedEventArgs(Button.ClickEvent, this));
}
}
And the handler:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
MessageBox.Show("Button was pressed");
}
This is by design, and is actually one of the reasons for RoutedEvents. They are called routed events because they are routed across the element tree. The behavior you are experiencing is called 'singular handler attachment point' on msdn. You specify that StackPanel should listen to all Button.Click events.
In your custom control, you raise a button click event. This 'bubbles' up to the stackpanel, which handles it.
UPDATE:
For this routing to work, I assume every UIElement needs to be able to raise any routed event. Routed Events are only used by UI elements, and are an answer to complexities with WinForms implementations. They aren't a replacement for CLR events.
The owner type is used internally when resolving an event by name.

MouseLeftButtonDown not recognized by a ListBox?

I'm encountering a huge problem, I have tried everything I could, but I didn't find any solution.
I have a listBox, with a DataTemplate. I want to use the events MouseLeftButtonDown and MouseLeftButtonUp to check the item selected is the same the user clicked on.
The problem is the event MouseLeftButtonUp is recognized but not the event MouseLeftButtonDown.
Part of my XAML code :
<ListBox Grid.Row="1" MouseLeftButtonDown="listBox_Faits_MouseLeftButtonDown"
MouseLeftButtonUp="listBox_Faits_MouseLeftButtonUp">
The code behind :
private void listBox_Faits_MouseLeftButtonUp(object sender, MouseEventArgs e)
{
...
}
private void listBox_Faits_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
...
}
Is anyone know why ?
Thanks you,
Regards,
Flo
This happens because the MouseLeftButtonDown event is getting handled by the list box item. To handle already handled events you can subscribe to it in code-behind and specify that you want to handle handled events, like this:
listBox_Faits.AddHandler(MouseLeftButtonDownEvent, new MouseButtonEventHandler(listBox_Faits_MouseLeftButtonDown), true);

Adding Events To WinForms?

I have a TextBox on a WinForm and I want to execute some code every time someone presses a key inside of that TextBox. I'm looking at the events properties menu, and see the KeyDown event, but don't know how to add code to it.
You need to add an event handler for that event. So in the properties menu, double-click on the field beside the KeyDown event and Visual Studio will create an event handler for you. It'll look something like this:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
// enter your code here
}
You can also subscribe to events yourself without using the Properties window. For example, in the form's constructor:
textBox1.KeyDown += HandleTextBoxKeyDownEvent;
And then implement the event handler:
private void HandleTextBoxKeyDownEvent(object sender, KeyEventArgs e)
{
// enter your code here
}
These answers will have visual studio generate the event and bind it behind the scenes in the Designer.cs file.
If you want to know how to bind events yourself, it looks like this.
MyTextBox.KeyDown += new KeyEventHandler(MyKeyDownFunction)
private function MyKeyDownFunction(object sender, KeyEventArgs e) {
// your code
}
If done this way, the new KeyEventHandler() part is optional. You can also use lambdas to avoid boilerplate code.
MyTextBox.KeyDown += (s, e) => {
// s is the sender object, e is the args
}
Doubleclick the textfield next to it.
I assume you are in Visual Studio. One way would be to double click on the empty textbox on the right of the KeyDown event: VS will generate the code for you.
You need to add a handler to the event.
Double-click the KeyPress event in the textbox's Properties window to make Visual Studio generate an event handler in the code file.
You can then put any code you want to inside the event handler function. You can check which key was pressed by writing e.KeyCode.

Categories