El siguiente enfoque es el mismo que Helge Klein, excepto que la ventana emergente se cierra automáticamente cuando se hace clic en cualquier lugar fuera de la emergente (incluyendo la propia 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 IsHitTestVisible la unión de modo que cuando hace clic en el ToggleButton de nuevo, la ventana emergente se cierra:
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 combining IValueConverter and 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, cerrar el popup puto ":.
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;
}
};
enfoque interesante – viggity
ver también @ enfoque de Qwertie - una versión más útil inspirado por esto que se cerrará la ventana emergente automáticamente cuando se alt-tab o haga clic fuera de la ventana emergente –