How to handle child event in parent control - wpf

In my main window, I have a child control(user control) which contains a text box . How can I handle the textchange event of the text box of child control in main(parent) window.
Please provide me some example with code as I am new to routing of events.

You should just be able to hook the event from the parent control. But since your parent control doesn't have a TextChanged event of its own, you'll need to use attached-property syntax:
<Window ...
TextBox.TextChanged="ChildTextBoxChanged">
and in your codebehind:
private void ChildTextBoxChanged(object sender, TextChangedEventArgs args)
{
...
}
You don't have to put the TextBox.TextChanged= on the Window specifically -- just any control that's a parent of the TextBox, i.e., any control that's a parent of your UserControl. The event will bubble up to each parent in turn, all the way up to the top-level Window, and can get handled anywhere along the way.
(Note that if anyone hooks the event and sets e.Handled = true, the event won't bubble past that point. Useful to know if you have handlers at multiple levels.)

this also helped me. I will have a event in the container of the child control and define the event in the code behind file. The event will handle all the text changed events for all the children.
<StackPanel TextBoxBase.TextChanged="test_TextChanged" Name="test">
<userControl/>
</StackPanel>

Create a event in your childcontrol -
public event TextChangedEventHandler TextChanged;
now add a handler for TextChanged event of TextBox in childcontrol -
private void TextBox_TextChanged(object sender, TextChangedEventArgs args)
{
if (TextChanged != null)
{
TextChanged.Invoke(this, args);
}
}
also update XAML for this handler -
<TextBox ... TextChanged="TextBox_TextChanged" ... />
Now, you have created a event in your childcontrol that fires when the Textbox's textchanged fires.
Now you only to add a handler for this event in mainwindow -
private void ChildControl_TextChanged(object sender, TextChangedEventArgs args)
{
//TODO: Add your further code here.
}

Related

Bind static method from another class as handler for WPF control event

I have a window, say MainWindow with some NumericUpDowns. I have another window MyCalculatorWindow like this:
public class MyCalculatorWindow : Window {
public static void LongUpDown_TouchUp(object sender, TouchEventArgs e)
{
// Show calculator and set numeric value when OK button is pressed.
}
// The rest of the MyCalculator functionality...
}
Is there a way to bind that static method to the TouchUp event handler property of LongUpDowns in xaml (ideally to all of them at once)? Something like this:
<xctk:LongUpDown TouchUp="{Binding Something??? MyCalculator.LongUpDown_TouchUp}" />
Is there a way to bind that static method to the TouchUp event handler property of LongUpDowns in xaml (ideally to all of them at once)? Something like this:
No, there isn't. The XAML compiler can only find event handlers in the same class as the element itself.
You could define a TouchUp event handler in the code-behind file for the view where the <xctk:LongUpDown /> element is and call the static method from there. It's a one-liner:
private void Window65_TouchUp(object sender, TouchEventArgs e) => MyCalculatorWindow.LongUpDown_TouchUp(sender, e);

Why does the KeyDown event bubble up from a TextBox?

If I type a letter into a TextBox, and its content changes according to my keypress, why does the KeyDown event continue bubbling up? I would have thought this would be 'handled' at this stage.
Since KeyDown event is a bubbling event, that's why its bubbled to its parent in your case Window. If you don't want that to bubbled to your window, you need to mark it as handled in your textBox handler itself like this -
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
}
Whereas, if you try to hook the event PreviewKeyDown in your textBox, you will see that - Window's PreviewKeyDownEvent gets called first and later that of your textBox. Reason behind that is, it's a tunelling event. For routing strategies, refer to this link - Routing Strategies
EDIT
Morevoer, if you want to check if the KeyDown event comes from textBox, you can check the OriginalSource of your eventArgs -
private void Window_KeyDown(object sender, KeyEventArgs e)
{
// Check to make sure event comes from window and not from textbox.
if(e.OriginalSource is Window)
{
}
}

Silverlight: How to Prevent Routing a MouseMove Event from a Child Canvas to Its Parent Canvas

I have my XAML code:
<Canvas x:Name="mainCanvas" Width="200" Height="150" Background="LightGray"
MouseLeftButtonUp="mainCanvas_MouseLeftButtonUp"
MouseMove="mainCanvas_MouseMove">
<Canvas x:Name="topCanvas" Width="200" Height="100" Background="LightBlue"
MouseLeftButtonUp="topCanvas_MouseLeftButtonUp"
MouseMove="topCanvas_MouseMove">
</Canvas>
</Canvas>
and its code behind:
private void topCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("topCanvas_MouseLeftButtonUp");
e.Handled = true; // This can prevent routing to the mainCanvas
}
private void mainCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("mainCanvas_MouseLeftButtonUp");
}
private void topCanvas_MouseMove(object sender, MouseEventArgs e)
{
Debug.WriteLine("topCanvas_MouseMove");
// How to prevent routing to the mainCanvas?
// e.Handled = true does NOT exist in MouseEventArgs
}
private void mainCanvas_MouseMove(object sender, MouseEventArgs e)
{
Debug.WriteLine("mainCanvas_MouseMove");
}
My question is already in the comments.
How to prevent routing the MouseMove event from the topCanvas (the child canvas) to the mainCanvas (parent canvas)?
Thanks.
Peter
Try setting the IsHitTestVisible property of your Canvas. With that property set accordingly mouse events will go either "through" your control or will be caught by it.
Hope this is what you need.
You can try comparing e.OriginalSource in mainCanvas's MouseMove Event and exit the Sub if it wasn't originated from the mainCanvas.
private void mainCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (sender != e.OriginalSource)
return;
}
In replying to your comment in a little more detail. According to the UIElement.MouseMove Event MSDN link.
Controls that inherit MouseMove can provide handling for the event
that acts as handler for all instances, by overriding the OnMouseMove
method. As with direct handling of the event, there is no Handled
property available, so OnMouseMove cannot be implemented in such a way
that it suppresses further handling of the event through the Handled
technique.
and this link states:
This event creates an alias for the Mouse.MouseMove attached event for
this class
Which brings us to this link on AttachedEvents which states.
Extensible Application Markup Language (XAML) defines a language
component and type of event called an attached event. The concept of
an attached event enables you to add a handler for a particular event
to an arbitrary element rather than to an element that actually
defines or inherits the event. In this case, neither the object
potentially raising the event nor the destination handling instance
defines or otherwise "owns" the event.
So as I see it, your only option is to code around it.
The functionality is called "Event Bubbling". You can stop it using below code:
jQuery:
event.stopPropagation();
Ref: http://api.jquery.com/event.stopPropagation/
You can also try below code:
e.stopPropagation(); //to prevent event from bubbling up
e.preventDefault(); //then cancel the event (if it's cancelable)
Ref: http://stackoverflow.com/questions/1967537/how-to-stop-event-bubbling-with-jquery-live
Thanks,
Ravi Verma

PreviewMouseDoubleClic handled ignored

I have a window containing a textBox.
On both the window AND the textBox, I add a PreviewMouseDoubleClicHandler.
Handler in the window:
private void PreviewMouseDoubleClickHandler(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("handler in the window");
e.Handled = true;
}
handler in the textBox:
private void PreviewMouseDoubleClickHandler(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("handler in the textBox");
e.Handled = true;
}
now, when I double-click on the textBox, I expect to go first into the window's Handler, print the debug line, then handle the event, then nothing more. I thought the textBox's handler would not fire since the event has already been handled by the window.
This does not work like this though: I get both handlers fired.
The weird thing is: It works fine with the PreviewMouseDown event. If I do exactly the same thing but with PreviewMouseDownEvents, I get the behavior I expect, i.e.: the window handles the mouseDown and the textBox's handler is not fired.
so Why does this not work with the doubleClick event? Am I doing something wrong? Is it supposed to work like this? is the doubleClick Event managed in a different way that prevents me from using the advantages of tunneling?
The behavior is by design, please see: http://msdn.microsoft.com/en-us/library/system.windows.controls.control.previewmousedoubleclick.aspx

WPF- Is it possible to add an OnVerticalOffsetChanged event to a custom textbox?

Is there any way for me to do this?
You can tell when the VerticalOffset changes by adding a handler to the ScrollViewer.ScrollChanged event to your TextBox. Something like this:
<TextBox AcceptsReturn="True" ScrollViewer.ScrollChanged="TextBox_ScrollChanged" />
The TextBox uses a ScrollViewer internally, so it's ScrollChanged event will bubble up to the TextBox (where you can handle it). The event arguments include information about what changed, such as the VerticalChange (the amount that the control has scrolled vertically).
private void TextBox_ScrollChanged(object sender, ScrollChangedEventArgs e) {
System.Diagnostics.Debug.WriteLine(string.Format("************ {0}", e.VerticalChange));
}

Resources