Как передать hitTest через элемент управления при выполнении операции перетаскивания - PullRequest
2 голосов
/ 09 ноября 2011

У меня есть элемент управления вкладками, который позволяет мне перетаскивать элементы вкладок из моего приложения.
Это перетаскивание откроет новое окно, которое будет следовать за мышью, пока я не отпущу левую кнопку мыши.
Также этоМожно перетащить элемент вкладки обратно в исходный элемент управления вкладкой и снова присоединить его к своему прежнему родительскому элементу или к любому другому элементу управления, способному понимать перетаскиваемые данные.

private static void DragOutTabControl_PreviewQueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
   e.Handled = true;

   if (DragControlIsHit)
   {
      if (_previewWindow != null && _previewWindow.IsVisible)
      {
         _previewWindow.Clear();
         _previewWindow.Hide();
      }
   }
   else
   {
      if (_previewWindow == null)
      {
         _previewWindow = new PreviewWindow();
         _previewWindow.SetData();
      }

      _previewWindow.Left = CursorPos.X - 15;
      _previewWindow.Top = CursorPos.Y - 15;
      _previewWindow.Show();
   }
}

Проблема, с которой я столкнулся сейчас, заключается в том, что когда окно предварительного просмотра следует за мышью, оно располагается непосредственно под курсором.
Таким образом, события dragEnter и dragOver элемента управления вкладки источника нестрельба, так как окно блокирует тестирование попадания.
Даже если я установлю IsHitTestVisible в false в окне, тестирование попадания будет заблокировано, пока перетаскивание все еще активно.
Установка IsEnabled в значение false и изменение фона на nullне иметь никакого эффекта.

public PreviewWindow()
{
   Background = null;
   IsEnabled = false;
   IsHitTestVisible = false;
}

Есть ли возможность скрыть окно предварительного просмотра от каких-либо тестов на попадание или передать тест на попадание вручную любому элементу управления визуально за перетаскиваемым окном?

Изменить, еще некоторую информацию длямоя проблема:
Я не только хочу перетаскивать элементы вкладок из элемента управления вкладками и открывать для них новые окна, но также хочу иметь возможность перетаскивать дополнительные элементы вкладок в существующие окна перетаскивания.
Кроме того, перетаскивание элемента вкладки обратно в исходный элемент управления вкладки должно быть возможным.

Все это работает довольно хорошо, за исключением единственной проблемы, которую я не могу скрыть в окне предварительного просмотра от тестирования перетаскивания и отбрасывания.

Ответы [ 2 ]

2 голосов
/ 14 ноября 2011

Ответ Рэйчел абсолютно верный, и я бы порекомендовал любому использовать обычные MouseEvents вместо DragDropEvents.
Но так как в моем приложении несколько окон, вовлеченных в перетаскивание, мне пришлось придуматьдругое решение:

private static void ProcessDraggedHitTest(
        Window window)
    {
        var CursorPos = GetCursorPos();
        var MousePosition = Mouse.GetPosition(window);

        IDragTarget hitControl = null;
        var hitTestResult = VisualTreeHelper.HitTest(window, new Point(CursorPos.X + MousePosition.X, CursorPos.Y + MousePosition.Y));
        if (hitTestResult != null)
        {
            var parent = hitTestResult.VisualHit as DependencyObject;
            while (parent != null)
            {
                hitControl = parent as IDragTarget;
                if (tileOutControl != null)
                    break;
                else
                    parent = VisualTreeHelper.GetParent(parent);
            }

            if (hitControl != null)
                DragOver(hitControl, _draggedItem);
        }
    }

, где DragOver (hitControl, _draggedItem) - это функция, которая обычно вызывается при возникновении события DragEnter или DragOver, а GetCursorPos () - это вызов Win32 для получения правильной позиции мыши.

Теперь вам нужно вызвать эти функции для всех окон в правильном z-порядке, и все готово.

Я надеюсь, что смогу помочь с моим решением, но если кто-нибудь найдет лучший способ сделать это, мне очень интересно узнать об этом.

1 голос
/ 09 ноября 2011

У меня был похожий вопрос о DragDrop тестировании попаданий событий, и ответ , который я получил, состоял в том, чтобы переключиться на использование MouseEvents вместо DragDrop событий.Я сделал это и ни разу не пожалел об этом, и никогда не пытался вернуться к встроенным в WPF событиям DragDrop.

В качестве альтернативы, если вы не хотите использовать мышь Mouse Events, можно показатьокно на слое Adorner вместо слоя пользовательского интерфейса и отображать его как новый объект только после того, как произойдет событие Drop.

...