Перетащите элемент управления всплывающим окном WPF

StackOverflow https://stackoverflow.com/questions/222029

  •  03-07-2019
  •  | 
  •  

Вопрос

Элемент управления всплывающими окнами WPF хорош, но, на мой взгляд, несколько ограничен.Есть ли способ «перетащить» всплывающее окно, когда оно открыто (например, с помощью метода Windows DragMove())?

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

Это было полезно?

Решение

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

  • Всплывающее окно подкласса в XAML и выделенном коде
  • Добавьте Thumb с шириной/высотой, равной 0 (это также можно сделать в XAML).
  • Прослушивайте события MouseDown во всплывающем окне и вызывайте то же событие в Thumb.
  • Переместить всплывающее окно на DragDelta

КСАМЛ:

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

    </Canvas>
</Popup>

С#:

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;
        };
    }
}

Другие советы

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));

        }
    }

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

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

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

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

<Ч>

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

  

Новое окно содержит дочернее содержимое всплывающего окна.      

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

<Ч>

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

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

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

Например, Popup.Child.MouseMove , Popup.Child.LostCapture и т. д.

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

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;
        }
    }

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

Опираясь на ответ Jobi Joy , я нашел повторно используемое решение, которое позволяет добавлять его как элемент управления в xaml существующего элемента управления / страницы. Который было невозможно добавить как Xaml с именем, так как он имеет другую область видимости.

    [ContentProperty("Child")]
    [DefaultEvent("Opened")]
    [DefaultProperty("Child")]
    [Localizability(LocalizationCategory.None)]
    public class DraggablePopup : Popup
    {
        public DraggablePopup()
        {
            MouseDown += (sender, e) =>
            {
                Thumb.RaiseEvent(e);
            };

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

        /// <summary>
        /// The original child added via Xaml
        /// </summary>
        public UIElement TrueChild { get; private set; }

        public Thumb Thumb { get; private set; } = new Thumb
        {
            Width = 0,
            Height = 0,
        };

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);

            TrueChild = Child;

            var surrogateChild = new StackPanel();

            RemoveLogicalChild(TrueChild);

            surrogateChild.Children.Add(Thumb);
            surrogateChild.Children.Add(TrueChild);

            AddLogicalChild(surrogateChild);
            Child = surrogateChild;
        }
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top