Pregunta ¿Hay alguna manera de evitar que un WPF Popup se reposicione cuando se sale de la pantalla?


¿Hay alguna manera de detener un WPF Surgir de reposicionarse cuando sale de la pantalla?

encontré esto vieja pregunta, pero no obtuvo una respuesta adecuada. ¿Hay alguna manera de hacer esto? Estoy dispuesto a subclasificar si es necesario. Gracias.


10
2018-01-08 04:24


origen


Respuestas:


Como señala Andrei, este comportamiento se encuentra en el interior Popup control y 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 algo de XAML como este:

<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 código detrás 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;
}

luego calculando que el Popup estaría fuera de la pantalla, podemos reducir el ancho del contenido y darle un margen negativo para que la porción que está en la pantalla quede recortada a lo que habría aparecido si el Popup fueron a permitir esto.

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


5
2018-01-08 20:01



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 una UpdatePosition método que ajustará la ubicación de la ventana emergente para que se mantenga entre los límites de la pantalla. Este método se llama desde varios lugares, desde On***Changed devoluciones de llamada (OnPlacementChanged, OnVerticalOffsetChanged, etc.)

Si realmente desea obtener esta funcionalidad, es posible que tenga una pequeña posibilidad de extender la clase Popup, anule algunos de los metadatos en las propiedades que se registraron con el On***Changed devoluciones de llamada para que UpdatePosition nunca se llama, sin embargo, la mayoría de la gente considerará que esto es pura maldad, tampoco lo recomiendo.


1
2018-01-08 06:54



no hay forma de que wpf framework coloque a Popup fuera de la pantalla, pero puede forzar la posición emergente llamando a "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);

            }


        }

1
2018-05-08 21:45



Puedes usar PrecisePopup control desde mi código abierto JungleControls biblioteca. 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 ubicación "Inferior" de la ventana emergente integrada, puede hacerlo así:

<jc:PrecisePopup PlacementTarget="{Binding ElementName=SomeTarget}"
                 IsOpen="{Binding IsOpen}">
    <jc:PrecisePopup.Placements>
        <jc:PrecisePopupPlacement VerticalTargetAlignment="Bottom" />
    </jc:PrecisePopup.Placements>
    <!-- Popup content here... -->
</jc:PrecisePopup>

0
2018-01-01 22:07



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

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


-1
2017-07-19 14:41