11
votes

Y a-t-il un moyen d'arrêter une popup WPF du repositionnement lui-même quand il passe à l'écran?

Y a-t-il un moyen d'arrêter un WPF Popup du repositionnement lui-même lorsqu'il passe hors écran?

J'ai trouvé ce ​​ancienne question , mais ça n'a pas obtenir une réponse appropriée. Y a-t-il un moyen de faire ça? Je suis prêt à la sous-classer si nécessaire. Merci.


0 commentaires

5 Réponses :


1
votes

Je ne pense pas qu'il y ait un moyen de faire cela. Au moins une manière propre. Si vous apercevez à la classe contextuelle avec le réflecteur, vous trouverez une méthode updatePosition qui ajustera l'emplacement de la pop up afin qu'il reste entre les limites de l'écran. Cette méthode est appelée à partir de plusieurs endroits, à partir de sur *** modifié Callbacks ( onplacementchanged , erverticaloffsetchanged , etc.).

Si vous voulez vraiment vraiment obtenir cette fonctionnalité, vous pouvez avoir une petite chance d'étendre la classe popup, remplacez certaines des métadonnées sur les propriétés enregistrées auprès du sur *** modifié Callbacks de sorte que Poste de mise à jour ne soit jamais appelé, mais la plupart des gens envisageront de faire cela pour être pur mal, je ne le recommande pas non plus.


0 commentaires

6
votes

Comme indique Andrei, ce comportement est profondément dans le contrôle de la pop up et durable à surmonter. Si vous êtes prêt à travailler, cela peut être fait en redimensionnant et en traduisant le contenu de la fenêtre contextuelle lorsqu'il atteint les bords d'écran. Aux fins de la démonstration, nous nous concentrerons sur le bord gauche de l'écran.

Si nous avons des xaml comme ceci: xxx

et code-indemnité ceci: xxx

puis en calculant que le document contextuel serait désactivé, nous pouvons réduire la largeur du contenu et lui donner une marge négative. de sorte que la partie qui soit à l'écran soit coupée à ce qui serait apparu si le document contextuel devait permettre cela.

Ceci devrait être étendu pour traiter les quatre bords de l'écran et la possibilité de plusieurs écrans, mais il démontre que l'approche est utilisable.


0 commentaires

0
votes

Vous pouvez utiliser PrecisePOPUP le contrôle de ma bibliothèque opensource JungleControls . Il postivera la popup exactement comme spécifié même si cela signifie que la fenêtre contextuelle est partiellement désactivée.

Il peut sélectionner automatiquement le placement le plus approprié parmi les placements que vous définissez, mais si vous avez juste besoin d'un placement PopUp exact qui correspond à Placement "inférieur" de la popup intégrée, vous pouvez le faire comme ceci: xxx


0 commentaires

-1
votes

Vous devez placer la fenêtre contextuelle et sa cible à l'intérieur du panneau de toile de sorte qu'elle ne repositionne pas en raison du problème de bord d'écran dans la commande contextuelle.

          <Canvas>
            <Rectangle Name="rectPopUp" Width="30" Height="30"/>
            <Button Width="20" Height="20" Name="btnAppLauncher" Click="btnAppLauncher_Click" Margin="-5,-2,0,0">
                <Button.Content>
                    <Path Fill="White" Stretch="Uniform" Data="M16,20H20V16H16M16,14H20V10H16M10,8H14V4H10M16,8H20V4H16M10,14H14V10H10M4,14H8V10H4M4,20H8V16H4M10,20H14V16H10M4,8H8V4H4V8Z"></Path>
                </Button.Content>
            </Button>
            <Popup Name="pnlAppLauncherPopup"  PlacementRectangle="0,25,0,0" PlacementTarget="{Binding ElementName=btnAppLauncher}" Placement="Bottom" AllowsTransparency="True" PopupAnimation="Slide">
                <UniformGrid Name="pnlAppLauncher">
                </UniformGrid>
            </Popup>
        </Canvas>


1 commentaires

Cette solution ne fonctionne pas pour moi. Lorsque vous déplacez mon popup près du bord de l'écran, il repositionnent en conséquence, quel que soit le conteneur en toile. J'ai essayé une cible de placement des pairs ainsi que d'utiliser le parent par défaut.



1
votes

Il n'y a aucun moyen de mettre en évidence la fenêtre contextuelle hors écran, mais vous pouvez forcer la position contextuelle en appelant "SetWindowpos" via p / invoke:

#region P/Invoke imports & definitions

        private const int HWND_TOPMOST = -1;
        private const int HWND_NOTOPMOST = -2;
        private const int HWND_BOTTOM = 1;
        private const int SWP_NOMOVE = 0x0002;
        private const int SWP_NOSIZE = 0x0001;
        private const int SWP_NOACTIVATE = 0x0010;
        private const int GW_HWNDPREV = 3;
        private const int GW_HWNDLAST = 1;


  [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        private static extern int SetWindowPos(IntPtr hWnd, int hwndInsertAfter, int x, int y, int cx, int cy, int wFlags); 

 #endregion

 private void updateposition(Item item)
        {
            if (item.IsOpen)
            {
                IntPtr hwnd = ((HwndSource)PresentationSource.FromVisual(item.popup.Child)).Handle;
                SetWindowPos(hwnd, 0, (int)item.WorkPoint.X, (int)item.WorkPoint.Y, (int)item.popup.Width, (int)item.popup.Height, SWP_NOSIZE | SWP_NOACTIVATE);

            }


        }


0 commentaires