visual ventanas ventana studio primera presentacion pasar pantalla otra formulario entre emergente ejemplos datos controles como aplicacion abrir wpf xaml popup eventtrigger

ventanas - ¿Cómo abrir una ventana emergente de WPF cuando se hace clic en otro control, utilizando solo el marcado XAML?



ventana emergente c# (5)

El siguiente enfoque es el mismo que el de Helge Klein, excepto que la ventana emergente se cierra automáticamente al hacer clic en cualquier lugar fuera de la ventana emergente (incluido el propio ToggleButton):

<ToggleButton x:Name="Btn" IsHitTestVisible="{Binding ElementName=Popup, Path=IsOpen, Mode=OneWay, Converter={local:BoolInverter}}"> <TextBlock Text="Click here for popup!"/> </ToggleButton> <Popup IsOpen="{Binding IsChecked, ElementName=Btn}" x:Name="Popup" StaysOpen="False"> <Border BorderBrush="Black" BorderThickness="1" Background="LightYellow"> <CheckBox Content="This is a popup"/> </Border> </Popup>

"BoolInverter" se utiliza en el enlace IsHitTestVisible para que al hacer clic en el ToggleButton nuevamente, se cierre la ventana emergente:

public class BoolInverter : MarkupExtension, IValueConverter { public override object ProvideValue(IServiceProvider serviceProvider) { return this; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is bool) return !(bool)value; return value; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return Convert(value, targetType, parameter, culture); } }

... que muestra la práctica técnica de combinar IValueConverter y MarkupExtension en uno.

Descubrí un problema con esta técnica: WPF tiene errores cuando aparecen dos ventanas emergentes en la pantalla al mismo tiempo. Específicamente, si su botón de alternar se encuentra en la "ventana emergente de desbordamiento" en una barra de herramientas, se abrirán dos ventanas emergentes después de hacer clic en él. A continuación, puede encontrar que la segunda ventana emergente (su ventana emergente) permanecerá abierta cuando haga clic en cualquier otro lugar en su ventana. En ese punto, cerrar la ventana emergente es difícil. El usuario no puede volver a hacer clic en ToggleButton para cerrar la ventana emergente porque IsHitTestVisible es falso porque la ventana emergente está abierta. En mi aplicación tuve que usar algunos hacks para mitigar este problema, como la siguiente prueba en la ventana principal, que dice (en la voz de Louis Black) "si la ventana emergente está abierta y el usuario hace clic fuera de la ventana emergente, cierre el friggin ''popup. ":

PreviewMouseDown += (s, e) => { if (Popup.IsOpen) { Point p = e.GetPosition(Popup.Child); if (!IsInRange(p.X, 0, ((FrameworkElement)Popup.Child).ActualWidth) || !IsInRange(p.Y, 0, ((FrameworkElement)Popup.Child).ActualHeight)) Popup.IsOpen = false; } };

Tengo dos controles, un TextBlock y un PopUp. Cuando el usuario hace clic (MouseDown) en el bloque de texto, quiero mostrar la ventana emergente. Pensaría que podría hacer esto con un EventTrigger en el Popup, pero no puedo usar setters en un EventTrigger, solo puedo comenzar storyboards. Quiero hacer esto estrictamente en XAML, porque los dos controles están en una plantilla y no sé cómo encontraría la ventana emergente en el código.

Esto es lo que conceptualmente quiero hacer, pero no puedo porque no se puede poner un colocador en un EventTrigger (como se puede hacer con un DataTrigger):

<TextBlock x:Name="CCD">Some text</TextBlock> <Popup> <Popup.Style> <Style> <Style.Triggers> <EventTrigger SourceName="CCD" RoutedEvent="MouseDown"> <Setter Property="Popup.IsOpen" Value="True" /> </EventTrigger> </Style.Triggers> </Style> </Popup.Style> ...

¿Cuál es la mejor manera de mostrar una ventana emergente estrictamente en XAML cuando ocurre un evento en un control diferente?


Hice algo simple, pero funciona.

Usé un ToggleButton típico, que rediseñé como un bloque de texto cambiando su plantilla de control. Luego acabo de vincular la propiedad IsChecked en ToggleButton a la propiedad IsOpen en la ventana emergente. Popup tiene algunas propiedades como StaysOpen que te permiten modificar el comportamiento de cierre.

Lo siguiente funciona en XamlPad.

<StackPanel> <ToggleButton Name="button"> <ToggleButton.Template> <ControlTemplate TargetType="ToggleButton"> <TextBlock>Click Me Here!!</TextBlock> </ControlTemplate> </ToggleButton.Template> </ToggleButton> <Popup IsOpen="{Binding IsChecked, ElementName=button}" StaysOpen="False"> <Border Background="LightYellow"> <TextBlock>I''m the popup</TextBlock> </Border> </Popup> </StackPanel>


Qué tal si:

<Button x:Name="OpenPopup">Popup <Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <BooleanAnimationUsingKeyFrames Storyboard.TargetName="ContextPopup" Storyboard.TargetProperty="IsOpen"> <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True" /> </BooleanAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Button.Triggers> </Button> <Popup x:Name="ContextPopup" PlacementTarget="{Binding ElementName=OpenPopup}" StaysOpen="False"> <Label>Popupcontent...</Label> </Popup>

Tenga en cuenta que Popup está haciendo referencia al Button por su nombre y viceversa. Entonces x:Name="..." es requerido en ambos, Popup y Button .

En realidad, se puede simplificar aún más al reemplazar las cosas del Storyboard con una Acción de Activar SetProperty personalizada de SetProperty descrita en esta SO Respuesta


Tuve algunos problemas con la parte de MouseDown de esto, pero aquí hay un código que puede comenzar.

<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Control VerticalAlignment="Top"> <Control.Template> <ControlTemplate> <StackPanel> <TextBox x:Name="MyText"></TextBox> <Popup x:Name="Popup" PopupAnimation="Fade" VerticalAlignment="Top"> <Border Background="Red"> <TextBlock>Test Popup Content</TextBlock> </Border> </Popup> </StackPanel> <ControlTemplate.Triggers> <EventTrigger RoutedEvent="UIElement.MouseEnter" SourceName="MyText"> <BeginStoryboard> <Storyboard> <BooleanAnimationUsingKeyFrames Storyboard.TargetName="Popup" Storyboard.TargetProperty="(Popup.IsOpen)"> <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="True"/> </BooleanAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> <EventTrigger RoutedEvent="UIElement.MouseLeave" SourceName="MyText"> <BeginStoryboard> <Storyboard> <BooleanAnimationUsingKeyFrames Storyboard.TargetName="Popup" Storyboard.TargetProperty="(Popup.IsOpen)"> <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False"/> </BooleanAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Control.Template> </Control> </Grid> </Window>


otra forma de hacerlo:

<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> <StackPanel> <Image Source="{Binding ProductImage,RelativeSource={RelativeSource TemplatedParent}}" Stretch="Fill" Width="65" Height="85"/> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> <Button x:Name="myButton" Width="40" Height="10"> <Popup Width="100" Height="70" IsOpen="{Binding ElementName=myButton,Path=IsMouseOver, Mode=OneWay}"> <StackPanel Background="Yellow"> <ItemsControl ItemsSource="{Binding Produkt.SubProducts}"/> </StackPanel> </Popup> </Button> </StackPanel> </Border>