Question

Le contrôle WPF Popup est agréable, mais quelque peu limité à mon avis. y a-t-il un moyen de "glisser" une fenêtre contextuelle lors de son ouverture (comme avec la méthode DragMove () de Windows)?

cela peut-il être fait sans gros problèmes ou dois-je écrire moi-même un substitut à la classe popup? merci

Était-ce utile?

La solution

Voici une solution simple en utilisant un pouce.

  • Popup de sous-classe en XAML et codebehind
  • Ajouter un pouce avec largeur / hauteur définie sur 0 (cela pourrait également être fait en XAML)
  • Écoutez les événements MouseDown sur le Popup et déclenchez le même événement sur le pouce
  • Déplacer la fenêtre contextuelle sur 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;
        };
    }
}

Autres conseils

Il n'y a pas de DragMove pour PopUp. Juste un petit travail, il y a beaucoup d'améliorations que vous pouvez ajouter à cela.

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

Dans le code derrière, ajoutez cet événement 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));

        }
    }

Pour cela, vous pouvez également définir le positionnement de votre Popup sur MousePoint. Cela fait apparaître initialement le popup à la position du curseur de la souris.

Vous pouvez ensuite utiliser un événement Thumb ou MouseMove pour définir les paramètres HorizontalOffset & amp; VerticalOffset. Ces propriétés éloignent le Popup de sa position d'origine au fur et à mesure que l'utilisateur le fait glisser.

N'oubliez pas de remettre à zéro HorizontalOffset et VerticalOffset pour la prochaine utilisation de la fenêtre contextuelle!

Le problème de perdre la souris en cas de déplacement trop rapide pourrait être résolu

Ceci provient de msdn:

  

La nouvelle fenêtre contient le contenu enfant de Popup.

     

Le contrôle Popup conserve une référence à son contenu enfant en tant qu'enfant logique. Lorsque la nouvelle fenêtre est créée, le contenu de Popup devient un enfant visuel de la fenêtre et reste l'enfant logique de Popup. Inversement, Popup reste le parent logique de son contenu enfant.

En d'autres termes, l'enfant de la fenêtre contextuelle est affiché dans une fenêtre autonome.

Donc, lorsque vous essayez les choses suivantes:
Popup.CaptureMouse () capture la fenêtre du wrapper et non le popup lui-même. Au lieu de cela, Popup.Child.CaptureMouse () capture la fenêtre contextuelle réelle.

Tous les autres événements doivent être enregistrés à l'aide de Popup.Child .

Comme Popup.Child.MouseMove , Popup.Child.LostCapture , etc.

Ceci a été testé et fonctionne parfaitement bien

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

Cela fonctionne pour faire glisser ma fenêtre, mais comme on me l'a dit, si je déplace la souris trop vite, elle sortirait de la fenêtre et cesserait de déclencher l'événement. Sans mentionner que le traînage n'est pas lisse du tout. Est-ce que quelqu'un sait comment le faire correctement, en glissant gentiment et en douceur, sans le perdre quand on le traîne trop vite ??? Si possible, postez un exemple simple, autre qu'un didacticiel complet qui aurait pour effet de faire perdre au débutant comme moi le code. Merci!

En me basant sur réponse de Jobi Joy , j'ai trouvé une solution réutilisable qui vous permet d'ajouter contrôle dans xaml d'un contrôle / page existant. Ce qui n’était pas possible en ajoutant Xaml avec un nom car il avait une portée différente.

    [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;
        }
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top