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 Offline
    K Offline
    Kevin Marois
    wrote on last edited by
    #1

    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 K 2 Replies 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}"
      
      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