Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. WPF
  4. Bubbling Event Question

Bubbling Event Question

Scheduled Pinned Locked Moved WPF
wpfquestioncsharpdotnetwcf
13 Posts 3 Posters 4 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Kevin Marois

    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}"
    
    L Offline
    L Offline
    Lost User
    wrote on last edited by
    #2

    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

    K 1 Reply Last reply
    0
    • L Lost User

      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

      K Offline
      K Offline
      Kevin Marois
      wrote on last edited by
      #3

      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.

      L 1 Reply Last reply
      0
      • K Kevin Marois

        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.

        L Offline
        L Offline
        Lost User
        wrote on last edited by
        #4

        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

        K 1 Reply Last reply
        0
        • L Lost User

          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

          K Offline
          K Offline
          Kevin Marois
          wrote on last edited by
          #5

          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.

          1 Reply Last reply
          0
          • K Kevin Marois

            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}"
            
            K Offline
            K Offline
            Kenneth Haugland
            wrote on last edited by
            #6

            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

            K 1 Reply Last reply
            0
            • K Kenneth Haugland

              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

              K Offline
              K Offline
              Kevin Marois
              wrote on last edited by
              #7

              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.

              K 1 Reply Last reply
              0
              • K Kevin Marois

                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.

                K Offline
                K Offline
                Kenneth Haugland
                wrote on last edited by
                #8

                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.

                K 1 Reply Last reply
                0
                • K Kenneth Haugland

                  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.

                  K Offline
                  K Offline
                  Kevin Marois
                  wrote on last edited by
                  #9

                  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.

                  K 1 Reply Last reply
                  0
                  • K Kevin Marois

                    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.

                    K Offline
                    K Offline
                    Kenneth Haugland
                    wrote on last edited by
                    #10

                    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;
                    }
                    }

                    K 1 Reply Last reply
                    0
                    • K Kenneth Haugland

                      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;
                      }
                      }

                      K Offline
                      K Offline
                      Kevin Marois
                      wrote on last edited by
                      #11

                      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.

                      K 1 Reply Last reply
                      0
                      • K Kevin Marois

                        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.

                        K Offline
                        K Offline
                        Kenneth Haugland
                        wrote on last edited by
                        #12

                        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)
                                { 
                                
                                }
                            }
                        
                        K 1 Reply Last reply
                        0
                        • K Kenneth Haugland

                          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)
                                  { 
                                  
                                  }
                              }
                          
                          K Offline
                          K Offline
                          Kevin Marois
                          wrote on last edited by
                          #13

                          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.

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups