Jac*_*cob 22 c# silverlight popup event-handling silverlight-3.0
在我的Silverlight UI中,我有一个按钮,当单击时会弹出一个带有一些过滤参数的控件.当你在它外面点击时,我希望这个控件隐藏起来.换句话说,它应该以类似于组合框的方式运行,但它不是组合框(您不选择其中的项目).这是我试图捕获控件之外的点击以解除它的方式:
public partial class MyPanel : UserControl
{
public MyPanel()
{
InitializeComponent();
}
private void FilterButton_Click(object sender, RoutedEventArgs e)
{
// Toggle the open state of the filter popup
FilterPopup.IsOpen = !FilterPopup.IsOpen;
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
// Capture all clicks and close the popup
App.Current.RootVisual.MouseLeftButtonDown += delegate {
FilterPopup.IsOpen = false; };
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,事件处理程序MouseLeftButtonDown永远不会被触发.是否有一种成熟的方法可以使弹出控件在你点击它之外时自动解除?如果没有,为什么我的MouseLeftButtonDown处理程序没有解雇?
解:
我想我会发布我的整个解决方案,以防其他人觉得它有用.在我的顶级视觉中,我为弹出窗口声明了一个"盾牌",如下所示:
<UserControl xmlns:my="clr-namespace:Namespace"
x:Class="Namespace.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:uriMapper="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
>
<Grid Background="Black" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<my:MyStuff/>
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
x:Name="PopupShield" Background="Transparent" Width="Auto"
Height="Auto" Visibility="Collapsed"/>
</Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)
然后,我为Popup类添加了一个扩展方法,如下所示:
public static class PopupUtils
{
public static void MakeAutoDismissing(this Popup popup)
{
var shield = (App.Current.RootVisual as MainPage).PopupShield;
// Whenever the popup opens, deploy the shield
popup.HandlePropertyChanges(
"IsOpen",
(s, e) =>
{
shield.Visibility = (bool)e.NewValue
? Visibility.Visible : Visibility.Collapsed;
}
);
// Whenever the shield is clicked, dismiss the popup
shield.MouseLeftButtonDown += (s, e) => popup.IsOpen = false;
}
}
public static class FrameworkUtils
{
public static void HandlePropertyChanges(
this FrameworkElement element, string propertyName,
PropertyChangedCallback callback)
{
//Bind to a depedency property
Binding b = new Binding(propertyName) { Source = element };
var prop = System.Windows.DependencyProperty.RegisterAttached(
"ListenAttached" + propertyName,
typeof(object),
typeof(UserControl),
new System.Windows.PropertyMetadata(callback));
element.SetBinding(prop, b);
}
}
Run Code Online (Sandbox Code Playgroud)
扩展方法使用如下:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
FilterPopup.MakeAutoDismissing();
}
Run Code Online (Sandbox Code Playgroud)
一种方法是将控件放在填充整个Silverlight表面的透明画布上.单击画布时,关闭画布并控制.如果要接收鼠标事件,确保将画布的背景画笔设置为"透明"非常重要.
我没有成功的另一种方法是在Silverlight中使用鼠标捕获并检测何时在弹出窗口外单击鼠标.