Bubbling Event Question
-
I have a CustomControl which contains another custom control. I want to bubble a click event from the Inner Control and handle it on the Window. Even better, can I somehow bind to the inner control's ButtonClicked command in the Window's VM? I found this two SO article. It's close, but it doesn't address custom events: [https://stackoverflow.com/questions/65894582/subscribe-to-any-bubbled-up-wpf-child-control-routed-event-without-an-instance-o\](https://stackoverflow.com/questions/65894582/subscribe-to-any-bubbled-up-wpf-child-control-routed-event-without-an-instance-o) Custom Controls
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BubblingEventsDemo"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"><Style TargetType="{x:Type local:InnerControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:InnerControl}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Button Content="Click Me" Height="32" Width="75"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <i:InvokeCommandAction Command="{Binding ButtonClickedCommand, RelativeSource={RelativeSource TemplatedParent}}"/> </i:EventTrigger> </i:Interaction.Triggers> </Button> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="{x:Type local:OuterControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:OuterControl}"> <Border Background="{TemplateBinding Background}"
-
I have a CustomControl which contains another custom control. I want to bubble a click event from the Inner Control and handle it on the Window. Even better, can I somehow bind to the inner control's ButtonClicked command in the Window's VM? I found this two SO article. It's close, but it doesn't address custom events: [https://stackoverflow.com/questions/65894582/subscribe-to-any-bubbled-up-wpf-child-control-routed-event-without-an-instance-o\](https://stackoverflow.com/questions/65894582/subscribe-to-any-bubbled-up-wpf-child-control-routed-event-without-an-instance-o) Custom Controls
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BubblingEventsDemo"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"><Style TargetType="{x:Type local:InnerControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:InnerControl}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Button Content="Click Me" Height="32" Width="75"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <i:InvokeCommandAction Command="{Binding ButtonClickedCommand, RelativeSource={RelativeSource TemplatedParent}}"/> </i:EventTrigger> </i:Interaction.Triggers> </Button> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="{x:Type local:OuterControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:OuterControl}"> <Border Background="{TemplateBinding Background}"
Handling an event higher up is "tunneling"; i.e. "Preview..." handlers.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
-
Handling an event higher up is "tunneling"; i.e. "Preview..." handlers.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
Umm, bubbling is UP and tunnleing is down: [https://stackoverflow.com/questions/16736444/difference-between-bubbling-and-tunneling-events\](https://stackoverflow.com/questions/16736444/difference-between-bubbling-and-tunneling-events) But this still doesn't answer the question of how do I handle an event on the parent from a nested user control Thanks
If it's not broken, fix it until it is. Everything makes sense in someone's mind. Ya can't fix stupid.
-
Umm, bubbling is UP and tunnleing is down: [https://stackoverflow.com/questions/16736444/difference-between-bubbling-and-tunneling-events\](https://stackoverflow.com/questions/16736444/difference-between-bubbling-and-tunneling-events) But this still doesn't answer the question of how do I handle an event on the parent from a nested user control Thanks
If it's not broken, fix it until it is. Everything makes sense in someone's mind. Ya can't fix stupid.
Handling it "higher" up BEFORE it goes DOWN, is "tunneling". The PARENT is the WINDOW ... and PREVIEW allows the PARENT to HANDLE the event before, or instead of, or in conjunction with ... the CHILD (i.e. the UC). This is called TUNNELING.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
-
Handling it "higher" up BEFORE it goes DOWN, is "tunneling". The PARENT is the WINDOW ... and PREVIEW allows the PARENT to HANDLE the event before, or instead of, or in conjunction with ... the CHILD (i.e. the UC). This is called TUNNELING.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
Bubbling vs Tunneling[^] Again, I'm trying to handle an event in the Window that was invoked in the nested child control. The event is defined as Bubbling, therefore it goes UP the UI stack
If it's not broken, fix it until it is. Everything makes sense in someone's mind. Ya can't fix stupid.
-
I have a CustomControl which contains another custom control. I want to bubble a click event from the Inner Control and handle it on the Window. Even better, can I somehow bind to the inner control's ButtonClicked command in the Window's VM? I found this two SO article. It's close, but it doesn't address custom events: [https://stackoverflow.com/questions/65894582/subscribe-to-any-bubbled-up-wpf-child-control-routed-event-without-an-instance-o\](https://stackoverflow.com/questions/65894582/subscribe-to-any-bubbled-up-wpf-child-control-routed-event-without-an-instance-o) Custom Controls
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BubblingEventsDemo"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"><Style TargetType="{x:Type local:InnerControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:InnerControl}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Button Content="Click Me" Height="32" Width="75"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <i:InvokeCommandAction Command="{Binding ButtonClickedCommand, RelativeSource={RelativeSource TemplatedParent}}"/> </i:EventTrigger> </i:Interaction.Triggers> </Button> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="{x:Type local:OuterControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:OuterControl}"> <Border Background="{TemplateBinding Background}"
I have solved similar things before with the use of an attached behavior so you use that to bind the command to a property in the VM
-
I have solved similar things before with the use of an attached behavior so you use that to bind the command to a property in the VM
Thanks. Do you have an example of that?
If it's not broken, fix it until it is. Everything makes sense in someone's mind. Ya can't fix stupid.
-
Thanks. Do you have an example of that?
If it's not broken, fix it until it is. Everything makes sense in someone's mind. Ya can't fix stupid.
You will need to install the NuGet: NuGet Gallery | Microsoft.Xaml.Behaviors.Wpf 1.1.39[^] Then create a class like this one:
public class ButtonAttatchment:Behavior { protected override void OnAttached() { AssociatedObject.Click += AssociatedObject\_Click; } protected override void OnDetaching() { AssociatedObject.Click -= AssociatedObject\_Click; } private void AssociatedObject\_Click(object sender, System.Windows.RoutedEventArgs e) { if (AssociatedObject != null) { ((ButtonAttatchment)sender).IsSpinning = !((ButtonAttatchment)sender).IsSpinning; } } public static readonly DependencyProperty IsSpinningProperty = DependencyProperty.Register("IsSpinning", typeof(bool),typeof(ButtonAttatchment), new UIPropertyMetadata(false)); public bool IsSpinning { get => (bool)GetValue(IsSpinningProperty); set => SetValue(IsSpinningProperty, value); } }
This basically creates a code-behind implementation that you could use to fix complicated binding issues.
-
You will need to install the NuGet: NuGet Gallery | Microsoft.Xaml.Behaviors.Wpf 1.1.39[^] Then create a class like this one:
public class ButtonAttatchment:Behavior { protected override void OnAttached() { AssociatedObject.Click += AssociatedObject\_Click; } protected override void OnDetaching() { AssociatedObject.Click -= AssociatedObject\_Click; } private void AssociatedObject\_Click(object sender, System.Windows.RoutedEventArgs e) { if (AssociatedObject != null) { ((ButtonAttatchment)sender).IsSpinning = !((ButtonAttatchment)sender).IsSpinning; } } public static readonly DependencyProperty IsSpinningProperty = DependencyProperty.Register("IsSpinning", typeof(bool),typeof(ButtonAttatchment), new UIPropertyMetadata(false)); public bool IsSpinning { get => (bool)GetValue(IsSpinningProperty); set => SetValue(IsSpinningProperty, value); } }
This basically creates a code-behind implementation that you could use to fix complicated binding issues.
Thanks. I'll give it a shot
If it's not broken, fix it until it is. Everything makes sense in someone's mind. Ya can't fix stupid.
-
Thanks. I'll give it a shot
If it's not broken, fix it until it is. Everything makes sense in someone's mind. Ya can't fix stupid.
The XAML code is like this:
And I made a slight mistake but Im sure you have figured it out by now:
private void AssociatedObject_Click(object sender, System.Windows.RoutedEventArgs e)
{
if (AssociatedObject != null)
{
IsSpinning = !IsSpinning;
}
} -
The XAML code is like this:
And I made a slight mistake but Im sure you have figured it out by now:
private void AssociatedObject_Click(object sender, System.Windows.RoutedEventArgs e)
{
if (AssociatedObject != null)
{
IsSpinning = !IsSpinning;
}
}Thanks for the code, but I'm not sure if this solves my issue. jFirst, see this image[^]. Second, see this[^]. It's almost what I want. There's got to be a way to do this. I put a demo in this repo[^]. See the MainWIndow's XAML.
If it's not broken, fix it until it is. Everything makes sense in someone's mind. Ya can't fix stupid.
-
Thanks for the code, but I'm not sure if this solves my issue. jFirst, see this image[^]. Second, see this[^]. It's almost what I want. There's got to be a way to do this. I put a demo in this repo[^]. See the MainWIndow's XAML.
If it's not broken, fix it until it is. Everything makes sense in someone's mind. Ya can't fix stupid.
Ok, I don't really see what you are getting at but it can be solved extremley easy:
And
private void Grid\_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (e.OriginalSource != null) { } }
-
Ok, I don't really see what you are getting at but it can be solved extremley easy:
And
private void Grid\_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (e.OriginalSource != null) { } }
Referring to the first pic with all the nested controls, I have this Routed even deep inside MyNewControl
public static readonly RoutedEvent ItemSelectedEvent =
EventManager.RegisterRoutedEvent("ItemSelected",
RoutingStrategy.Tunnel,
typeof(RoutedEventHandler),
typeof(NavigationPane));public event RoutedEventHandler ItemSelected
{
add { AddHandler(ItemSelectedEvent, value); }
remove { RemoveHandler(ItemSelectedEvent, value); }
}private void RaiseItemSelectedEvent()
{
// Raise the event, passing the selected item
vars args = new SelectedItemEventArgs(ItemSelectedEvent, SelectedItem);
RaiseEvent(args);
}How do I catch this event in the window? What is the syntax? Using some kind of Preview_... is going to catch a LOT of events. Is there no way to subscribe directly to that event from the Window?
If it's not broken, fix it until it is. Everything makes sense in someone's mind. Ya can't fix stupid.