Перетащите элемент управления WPF Popup

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
20
0
31 972
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

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

        }
    }
Ой! Нет, используйте вместо этого Thumb и его событие DragDelta (выберите DragStarted / DragCompleted, если вы хотите управлять состояниями). Это намного эффективнее, не будет фрагментировать память и не будет рисковать потерять мышь, как в примере выше. Вот так правильно делается перетаскивание :) См. Пример здесь.
RedGlyph 02.09.2010 23:37

Я согласен, это решение, которое я дал, - это просто взлом. Как вы сказали, DragDelta более производительна, чем MoveMove.

Jobi Joy 03.09.2010 01:16

Но что, если вы не хотите злоупотреблять всплывающим окном в качестве большого пальца (что, я думаю, я имел в виду в комментарии RedGlyphs), но хотите переместить более сложное всплывающее окно (например, наложение видео). использование явного окна не вариант в моем сценарии.

Joachim Kerschbaumer 26.07.2011 17:39
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;
        }
    }

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

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

Joachim Kerschbaumer 02.05.2011 15:02

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

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

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

Ответ принят как подходящий

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

  • Всплывающее окно подкласса в XAML и выделенном коде
  • Добавьте Thumb с шириной / высотой, равной 0 (это также можно сделать в XAML)
  • Слушайте события MouseDown во всплывающем окне и вызывайте то же событие в Thumb
  • Переместить всплывающее окно на 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;
        };
    }
}

Возможно, мне не хватает чего-то простого, что знал бы опытный разработчик WPF, но как это можно использовать повторно? Когда я помещаю элемент управления в другой контекст XAML (например, пытаюсь повторно использовать его в окне), любое указанное мной содержимое переопределяет элемент Canvas, к которому привязан ползунок.

Vassi 18.01.2013 22:18

Я пробовал это решение. Прекрасно работает! Спасибо, Джейкоб. Я столкнулся только с одной проблемой: у меня есть представление внутри этого пальца, и я могу нормально перетащить весь вид, однако, если в этом представлении есть полоса прокрутки, перетаскивание полосы прокрутки вызывает перетаскивание большого пальца и, следовательно, всего представления. Есть ли способ этого избежать?

Shankar Raju 19.03.2014 02:09

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


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

The new window contains the Child content of Popup.

The Popup control maintains a reference to its Child content as a logical child. When the new window is created, the content of Popup becomes a visual child of the window and remains the logical child of Popup. Conversely, Popup remains the logical parent of its Child content.


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

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

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

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

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

Да, захват мыши - правильный способ справиться с перетаскиванием. Все это e.Leftbutton == Pressed немного лениво и вызывает некоторые побочные эффекты.

Alan 31.10.2012 00:07

Основываясь на ответе Джоби Джой, я нашел решение многократного использования, которое позволяет вам добавлять в качестве элемента управления в 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;
        }
    }

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