2008-10-21 10 views
16

Управление всплывающим окном WPF приятно, но несколько ограничено, на мой взгляд. есть ли способ «перетащить» всплывающее окно при его открытии (например, с помощью метода DragMove() для окон)?Drag WPF Popup control

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

ответ

13

Вот простое решение с использованием Thumb.

  • Подкласс всплывающих окон в XAML и отделенного кода
  • Добавить пальцу ширина/высота значение 0 (это также может быть сделано в XAML)
  • Прислушайтесь MouseDown событий на Popup и поднять то же событие на Большой палец
  • Переместить всплывающее окно на DragDelta

XAML:

<Popup x:Class="PopupTest.DraggablePopup" ...> 
    <Canvas x:Name="ContentCanvas"> 

    </Canvas> 
</Popup> 

C#:

public partial class DraggablePopup : Popup 
{ 
    public DraggablePopup() 
    { 
     var thumb = new Thumb 
     { 
      Width = 0, 
      Height = 0, 
     }; 
     ContentCanvas.Children.Add(thumb); 

     MouseDown += (sender, e) => 
     { 
      thumb.RaiseEvent(e); 
     }; 

     thumb.DragDelta += (sender, e) => 
     { 
      HorizontalOffset += e.HorizontalChange; 
      VerticalOffset += e.VerticalChange; 
     }; 
    } 
} 
16

Нет DragMove для PopUp. Просто небольшая работа вокруг, есть много улучшений, которые вы можете добавить к этому.

<Popup x:Name="pop" IsOpen="True" Height="200" Placement="AbsolutePoint" Width="200"> 
    <Rectangle Stretch="Fill" Fill="Red"/>    
</Popup> 

В коде позади, добавить событие MouseMove

pop.MouseMove += new MouseEventHandler(pop_MouseMove); 

    void pop_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (e.LeftButton == MouseButtonState.Pressed) 
     { 
      pop.PlacementRectangle = new Rect(new Point(e.GetPosition(this).X, 
       e.GetPosition(this).Y),new Point(200,200)); 

     } 
    } 
+16

** ** Ой! Нет, используйте [`Thumb`] (http://msdn.microsoft.com/en-us/library/ms749252%28VS.100%29.aspx) и его событие` DragDelta` вместо этого (выберите «DragStarted»/`DragCompleted`, если вы хотите управлять состояниями). Это намного эффективнее, не будет фрагментировать память и не рискует потерять мышь в качестве примера выше. Вот как перетаскивание выполняется правильно :) См. Здесь [здесь] (http://www.codeproject.com/KB/WPF/TubePlanner.aspx). – RedGlyph 2010-09-02 19:37:33

+0

Я согласен, что решение, которое я дал, это просто взломать. Как вы сказали, DragDelta более совершенен, чем MoveMove. – 2010-09-02 21:16:44

+1

Но что, если вы не хотите злоупотреблять всплывающим окном в виде большого пальца (что, я думаю, я имел в виду в комментарии RedGlyphs), но вы хотите переместить более сложное всплывающее окно (например, наложение видео). использование явного окна не является вариантом в моем сценарии. – 2011-07-26 13:39:57

0
Private Point startPoint; 

private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 

     startPoint = e.GetPosition(null); 
    } 
private void Window_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (e.LeftButton == MouseButtonState.Pressed) 
     { 
      Point relative = e.GetPosition(null); 
      Point AbsolutePos = new Point(relative.X + this.Left, relative.Y + this.Top); 
      this.Top = AbsolutePos.Y - startPoint.Y; 
      this.Left = AbsolutePos.X - startPoint.X; 
     } 
    } 

Это работает для перетаскивания моего окна, но, как было сказано, если я двигаю мышь, чтобы быстро, получить бы из окна и остановить поднятие события. Не говоря уже о том, что перетаскивание не является гладко. Кто-нибудь знает, как это сделать правильно, приятно и плавно перетаскивать, не теряя при перетаскивании слишком быстро ??? Отправьте простой пример, если это возможно, за исключением целого учебника, в котором бы начинающие, как я потерял код. Благодаря!

+0

вы могли бы захватить мышь, чтобы избежать проблемы, о которой вы говорили, когда мышь выходит из окна. – 2011-05-02 11:02:55

2

Другой способ достижения этого - установить размещение всплывающего окна в MousePoint. Это приводит к тому, что всплывающее окно сначала появляется в позиции курсора мыши.

Затем вы можете использовать событие Thumb или MouseMove, чтобы установить HorizontalOffset всплывающего окна & VerticalOffset. Эти свойства сдвигают всплывающее окно в исходное положение, когда пользователь тащит его.

Не забудьте вернуть HorizontalOffset и VerticalOffset обратно к нулю для следующего использования всплывающего окна!

2

Проблема с потерей мыши при перемещении слишком быстро, может быть решена


Это взято из MSDN:

Новое окно содержит ребенка содержимое Popup.

Элемент управления Popup поддерживает ссылку на его дочернее содержимое как логическое дочернее. Когда создается новое окно, содержимое Popup становится визуальным дочерним элементом окна и остается логическим дочерним элементом Popup. И наоборот, Popup остается логическим родителем своего дочернего контента.


В Другими словами, ребенок всплывающего окна отображается в самостоятельном окне.

Поэтому при попытке выполнить следующие действия:
Popup.CaptureMouse() Захват окна обертки, а не всплывающее окно. Вместо использования Popup.Child.CaptureMouse() захватывает фактическое всплывающее окно.

И все другие события должны быть зарегистрированы с использованием Popup.Child.

Как Popup.Child.MouseMove, Popup.Child.LostCapture и так далее

Это было проверено и работает прекрасно