Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Listview datatemplate with combobox has drag issues #84

Closed
osicka opened this issue Feb 3, 2014 · 5 comments
Closed

Listview datatemplate with combobox has drag issues #84

osicka opened this issue Feb 3, 2014 · 5 comments
Assignees
Milestone

Comments

@osicka
Copy link

osicka commented Feb 3, 2014

Hi,

I have a listview with a datatemplate that has many embedded controls, date picker, textbox, etc.

If I put a combobox in the datatemplate, drop down the list and try and scroll the drop down list with the vertical scrollbar the listviewitem starts dragging instead.

The solution that I found was to add an additional check to the hit tests that passes the original source as follows:

HitTest4Type(e.OriginalSource, e)

There are some quite funny useability issues still though. If you hold your mouse down on an item in the combobox drop down list and move your mouse the listviewitem also starts to drag. I didn't try to solve this issue as the user is less likely to try this.

Thanks
Anthony

@wintah
Copy link

wintah commented Feb 4, 2014

Just installed this from nuget and also run into this (using ListBox). I expect that below template should be enough to reproduce.

<ListBox.ItemTemplate>
 <DataTemplate>
  <ComboBox Text="Text">
   <ComboBoxItem>Item1</ComboBoxItem>
   <ComboBoxItem>Item2</ComboBoxItem
  </ComboBox>
 </DataTemplate>
</ListBox.ItemTemplate>

edit: Adding

|| HitTestUtilities.HitTest4Type<ComboBox>(sender, elementPosition)

to

private static void DragSource_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 

in DragDrop.cs fixes this.

@osicka
Copy link
Author

osicka commented Feb 4, 2014

I used the combobox as an example but this is an issue for any control in the datatemplate that has left mouse button interaction. It would be nice to have a generic solution, otherwise you need to add every possible control to the list of exclusions. It gets even worse, when you have custom controls that would have to also be added.

@punker76
Copy link
Owner

punker76 commented Feb 4, 2014

I will fix this issue as possible as soon

@wintah
Copy link

wintah commented Feb 5, 2014

Ah, right. After going through the code and debugging what's is happening, the reason that the current HitTest4Type's need to be quite specific is that the GetVisualAncestor keeps going after it has passed the container. Thus you will get false hits from borders of the window and so on.

public static T GetVisualAncestor<T>(this DependencyObject d) where T : class
-->
public static T GetVisualAncestor<T>(this DependencyObject d, object source = null) where T : class
----
while (item != null) {
-->
while (item != null && item != source) {

private static T GetHitTestElement4Type<T>(object sender, Point elementPosition) where T : UIElement
----
var uiElement = hit.VisualHit.GetVisualAncestor<T>();
-->
var uiElement = hit.VisualHit.GetVisualAncestor<T>(sender);

Then the hit tests can be a bit more generic:

private static void DragSource_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)

For example both Slider and ScrollBar match RangeBase

|| HitTestUtilities.HitTest4Type<RangeBase>(sender, elementPosition)

Not sure that this will address osicka's problems completely, and the specific hit tests need to be added (such as Selector, RangeBase). Hopefully I included all the changes, tried a few things before this.

@osicka
Copy link
Author

osicka commented Feb 5, 2014

That did not work for me, I think because it is doing the hit test on the sender, which doesn't work when the original source is part of a popup (e.g. ComboBox drop down), the hit test needs to be done on the original source.

Because the popup is not attached to the visual tree of the sender, I added a new function to test this by looping back from the original source to the sender and if I didn't end up at the sender stopped the drag:

    static bool IsNotPartOfSender(object sender, MouseButtonEventArgs e)
    {
        HitTestResult hit = VisualTreeHelper.HitTest((Visual)e.OriginalSource, e.GetPosition((IInputElement)e.OriginalSource));

        if (hit == null)
        {
            return false;
        }
        else
        {
            DependencyObject item = VisualTreeHelper.GetParent(e.OriginalSource as DependencyObject);

            while (item != null && item != sender)
            {
                item = VisualTreeHelper.GetParent(item);
            }

            return item != sender;
        }
    }

And in DragSource_PreviewMouseLeftButtonDown I added

|| IsNotPartOfSender(sender, e)

This fixed the majority of my problems, the only remaining problem is my custom controls which inherit from Control so I cannot add them to the exclusion list unless I linking in my custom control library.

punker76 added a commit that referenced this issue Feb 13, 2014
- it's now possible to select combox and items, and use the srollbar and
mousewheel
- introduce CanStartDrag method for IDragSource to handle starting
drag&drop
@punker76 punker76 added this to the v0.1.4 milestone May 28, 2014
@punker76 punker76 self-assigned this May 28, 2014
punker76 added a commit that referenced this issue Aug 30, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants