简体   繁体   中英

Can I make this easier? Bubbling vs Tunneling in WPF?

I am working with drag and drop functionality in a WPF application.

I have a tree structure such as the following.

StackPanel
 - Border 1
   - Grid A
     - Grid 1
     - Grid 2
 - Border 2
   - Grid B
     - Grid 1
     - Grid 2

This is my attempt to show the tree representation of the UIElements in my WPF application.

so the stack panel contains Grids with nested grids within it. These are being defined dynamically in code, and not in XAML.

I have the inner Grids(1 & 2) handling Drag and Drop events. The problem I am having is that when a drop operation is being performed, and it is dropped on the border of one of the grids, it falls through and hits the StackPanel Drop. What I would like to do is when an item is dropped on the border, I would like it to fall through to the same drop event handler.

I am fairly new to the idea of Routed Events and Bubbling and Tunneling events. I am aware that I need this event to travel down the element hierarchy which makes me believe that I am in need for "Tunneling" Event. Does this mean that I am supposed to attach the border to an event handler. Right now I have the following code for the Grids to be subscribed to the event.

fieldItemGrid.PreviewDrop += Grid_Drop;

private void Grid_Drop(object sender,DragEventArgs e)
{
        //React to Drop Event Here
}

Am I able to do something simpler then rewriting the code that goes here in a Border_Drop Event?

Thanks ahead of time.

I think it would be best to add a very tight (no padding) container (eg, a Grid) around the area that should act as a dropzone. Then use the tight container to handle the drop.

this way it doesn't matter what borders are specified. Only a padding of the tight container or a margin on the child controls will then mess it up.

The way routing working the preview event starts at the top of the tree until it reaches the element that initiated the event and then the normal event starts at the element itself and works towards the top of the tree.

In your situation, if border is the drop target, the sequence goes this (if event goes unhandled):

  • PreviewDrop -> StackPanel
  • PreviewDrop -> Border
  • Drop -> Border
  • Drop -> StackPanel

so the event will never reach any of the inner grids when the drop occurs on an element outside the grids. In other words, it will never tunnel into any children of the drop target because the tunnel stops where the drop occurred. It makes sense, how would it know which child was the right child to tunnel into if there were more than one?

As a result, you have to install the drop event handler on the largest element that visually represents the conceptual drop target. You can either switch the order of "Border 1" and "Grid A" or move your drop event handler for "Grid A" to "Border 1".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM