【问题标题】:WPF - How Combobox knows when to close the drop down menuWPF - Combobox 如何知道何时关闭下拉菜单
【发布时间】:2009-09-15 05:22:07
【问题描述】:

我想编写一个类似于ComboBox 的控件,我想知道是否有人知道如何检测用户何时在ComboBox 边界之外单击。 ComboBox 在这种情况下关闭它的下拉菜单。

【问题讨论】:

  • 一个问题,你为什么要写你的​​combo,如果你可以根据需要自定义wpf的combo?
  • 我试过了。但问题是键盘不适用于组合框中的自定义控件。实际上,组合框中的自定义控件是一个非格鲁吉亚日期时间选择器。

标签: .net wpf combobox controls


【解决方案1】:

您可以使用文本框和弹出窗口定义自己的自定义控件和控件模板。然后覆盖控件的 OnApplyTemplate 方法并使用以下命令查找弹出窗口:

var popup = this.GetTemplateChild("PART_Popup") as Popup;

现在您可以通过将其 IsOpen 属性设置为 true 或 false 来决定何时显示或隐藏弹出窗口。

要了解用户是否点击了 UI 的其他部分,只需订阅控件父级上的 PreviewMouseDown 事件(在控件初始化代码中的某个位置):

var parent = VisualTreeHelper.GetParent(this) as UIElement;
if(parent != null) {
    parent.PreviewMouseDown += MouseDownHandler;
}

现在,当用户单击控件容器内的任何位置时,您应该会收到通知。您还可以递归地使用 VisualTreeHelper.GetParent(...) 来获取根元素(例如窗口),直到它返回 null。

弹出窗口将不在同一个可视化树中,因此如果您想知道用户何时在弹出窗口内单击,则需要为弹出窗口的根元素定义鼠标事件处理程序。

【讨论】:

    【解决方案2】:

    多年前,我对 Silverlight 的早期版本也有同样的疑问。我检查了控件模板并反编译了 Microsoft 代码,发现它们在整个窗口中使用了不可见的覆盖层来检测点击。 WPF 组合框的工作方式似乎不同,但您可以遵循 Silverlight 模式。

    您需要创建一个与窗口大小相同的矩形。我通过使用 RowSpan 来覆盖包含我的整个应用程序的主 Grid 来做到这一点。您还可以将高度/宽度绑定到窗口高度/宽度。有十几种方法可以做到,只要让它填满你的整个窗口。给矩形填充颜色为白色,不透明度为 0。它确实需要填充颜色才能工作,但是不透明度 = 0 时,用户将看不到它。出于调试目的,您可以给它 Red 和 Opacity .25。

    <Rectangle x:Name="fullScreenOverlay" Grid.RowSpan="3" Opacity="0" Fill="White" Visibility="Collapsed" MouseDown="FullScreenOverlay_OnMouseDown" />
    

    其中一个关键部分是将 Rectangle 放在 XAML 的底部,以便它呈现在任何其他 XAML 控件之上。

    当您打开类似 ComboBox 的控件时,将此矩形设置为可见,以便它可以检测点击/MouseDown。

    private void NotificationButton_Click(object sender, RoutedEventArgs e)
    {
        fullScreenOverlay.Visibility = Visibility.Visible;
        notificationPopup.Visibility = Visibility.Visible;
    }
    

    当您检测到点击时,将 Rectangle 设置回折叠状态,然后像弹出窗口一样关闭您的 ComboBox。全部完成。

    private void FullScreenOverlay_OnMouseDown(object sender, MouseButtonEventArgs e)
    {
        fullScreenOverlay.Visibility = Visibility.Collapsed;
        notificationPopup.Visibility = Visibility.Collapsed;
    }
    

    这不会像 Microsoft ComboBox 那样检测应用程序外部发生的点击。它只会检测应用程序内部的点击。但坦率地说,我还是更喜欢这样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-24
      • 1970-01-01
      • 2021-06-24
      相关资源
      最近更新 更多