2011-01-08 8 views

Respuesta

5

Como señala Andrei, este comportamiento se encuentra en el interior del control Popup y es difícil de superar. Si está dispuesto a hacer algún trabajo, puede hacerlo cambiando el tamaño y traduciendo el contenido de la ventana emergente cuando alcanza los bordes de la pantalla. Para los propósitos de la demostración, nos enfocaremos en el borde izquierdo de la pantalla.

Si tenemos un poco de XAML como esto:

<Window ... 
     LocationChanged="Window_LocationChanged" 
     SizeChanged="Window_SizeChanged" 
     > 
    <Grid> 
     <Rectangle Name="rectangle1" Width="100" Height="100" Fill="Blue"/> 
     <Popup Name="popup1" PlacementTarget="{Binding ElementName=rectangle1}" IsOpen="True" Width="100" Height="100"> 
      <TextBlock Background="White" TextWrapping="Wrap" Width="100" Height="100"> 
       <TextBlock.Text>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</TextBlock.Text> 
      </TextBlock> 
     </Popup> 
    </Grid> 
</Window> 

y de código subyacente de esta manera:

private void Window_LocationChanged(object sender, EventArgs e) 
{ 
    RefreshPopupPosition(); 
} 

private void Window_SizeChanged(object sender, SizeChangedEventArgs e) 
{ 
    RefreshPopupPosition(); 
} 

private void RefreshPopupPosition() 
{ 
    var upperLeft = rectangle1.PointToScreen(new Point(0, 100)); 
    var xOffset = Math.Min(0, upperLeft.X); 
    popup1.Width = xOffset + 100; 
    (popup1.Child as FrameworkElement).Margin = new Thickness(xOffset, 0, 0, 0); 
    popup1.HorizontalOffset += 1; 
    popup1.HorizontalOffset -= 1; 
} 

continuación, calculando que el Popup sería fuera de la pantalla, podemos reducir el ancho del contenido y darle un margen negativo para que la porción que está en pantalla se recorta a lo que habría aparecido si el Popup fuera a permitir esto.

Esto debería extenderse para ocuparse de los cuatro bordes de la pantalla y la posibilidad de pantallas múltiples, pero demuestra que el enfoque es factible.

1

No creo que haya una manera de hacer esto. Al menos de una manera limpia. Si echas un vistazo a la clase Popup con el reflector, encontrarás un método UpdatePosition que ajustará la ubicación de la ventana emergente para que permanezca entre los límites de la pantalla. Este método se llama desde varios lugares, desde On***Changed callbacks (OnPlacementChanged, OnVerticalOffsetChanged, etc.).

Si realmente realmente desea conseguir esta funcionalidad, es posible que tenga una pequeña posibilidad de extender la clase emergente, anular algunos de los metadatos de las propiedades que se registraron con las devoluciones de llamada On***Changed de manera que nunca se UpdatePosition es llamado, sin embargo la mayoría de la gente considerará que hacer esto es pura maldad, tampoco lo recomiendo.

0

Puede usar el control PrecisePopup desde mi biblioteca de código abierto JungleControls. Posicionará la ventana emergente exactamente como se especificó, incluso si eso significa que la ventana emergente está parcialmente fuera de la pantalla.

Puede seleccionar automáticamente la ubicación más adecuada entre las ubicaciones que defina, pero si solo necesita una ubicación emergente exacta que corresponda a la colocación "Inferior" del Popup incorporado, puede hacerlo así:

-1

Tiene que colocar la ventana emergente y su destino dentro del panel Lienzo para que no se vuelva a colocar debido al problema de borde de la pantalla en el control emergente.

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

Dado que toda la unidad está dentro del panel de lienzo y se coloca el rectángulo de colocación, la ventana emergente se mostrará debajo del rectángulo.

+0

Esta solución no funciona para mí. Cuando muevo mi ventana emergente cerca del borde de la pantalla, se reposiciona en consecuencia independientemente del contenedor Canvas. Probé un objetivo de ubicación entre iguales, así como el uso del padre predeterminado. – Brannon

0

no hay manera de marco WPF para poner fuera de la pantalla emergente, pero puede forzar la posición emergente llamando "SetWindowPos" a través de 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); 

      } 


     } 
Cuestiones relacionadas