Y a-t-il un moyen d'arrêter un WPF Popup du repositionnement lui-même lorsqu'il passe hors écran? P>
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. P>
5 Réponses :
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 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 updatePosition code> 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é code> Callbacks (
onplacementchanged code>,
erverticaloffsetchanged code>, etc.). P>
sur *** modifié code > Callbacks de sorte que
Poste de mise à jour code> ne soit jamais appelé, mais la plupart des gens envisageront de faire cela pour être pur mal, je ne le recommande pas non plus. P>
Comme indique Andrei, ce comportement est profondément dans le contrôle de la pop up code> 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: p> et code-indemnité ceci: p> puis en calculant que le document contextuel code> 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 code> devait permettre cela. p> 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. p> p>
Vous pouvez utiliser PrecisePOPUP a> 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: p>
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>
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.
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); } }