求助:WPF自定义DatePicker实现点击外部关闭日历弹窗的方案
自定义DatePicker点击外部关闭日历的解决方案
问题原因
你的StackPanel默认Focusable属性为False,无法获得焦点,因此LostFocus事件不会被触发,导致点击外部区域无法关闭日历。
解决方案1:让StackPanel可聚焦并处理焦点丢失
修改XAML中的红色StackPanel,添加Focusable="True"属性,确保它能获得焦点;同时在点击事件中手动让它获取焦点,这样点击外部时就会触发LostFocus事件。
修改后的XAML片段:
<StackPanel MouseLeftButtonDown="TextBlock_Click" Orientation="Horizontal" Background="Red" Height="33" LostFocus="StackPanel_LostFocus" Focusable="True"> <TextBlock Text="{Binding ApptNotScheduledStartDate, StringFormat='{}{0:MMM dd, yyyy}'}" /> <materialDesign:PackIcon Kind="ChevronDown"/> </StackPanel>
修改后台的TextBlock_Click方法:
private void TextBlock_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { MyDatePicker.IsDropDownOpen = !MyDatePicker.IsDropDownOpen; // 让StackPanel获取焦点,确保LostFocus能触发 ((StackPanel)sender).Focus(); }
解决方案2:监听窗口鼠标点击事件判断点击区域
如果方案1不满足需求,可以通过监听窗口的PreviewMouseDown事件,判断点击的元素是否属于DatePicker的子元素,若不属于则关闭日历下拉。
- 在窗口的XAML中添加事件绑定:
<Window ... PreviewMouseDown="Window_PreviewMouseDown">
- 后台添加事件处理方法和辅助判断方法:
private void Window_PreviewMouseDown(object sender, MouseButtonEventArgs e) { var clickedElement = e.OriginalSource as FrameworkElement; if (clickedElement != null && !IsElementInDatePicker(clickedElement)) { MyDatePicker.IsDropDownOpen = false; } } // 判断点击的元素是否是DatePicker的子元素 private bool IsElementInDatePicker(FrameworkElement element) { var currentParent = element.Parent as FrameworkElement; while (currentParent != null) { if (currentParent == MyDatePicker) return true; currentParent = currentParent.Parent as FrameworkElement; } return false; }
额外优化:选择日期后自动关闭
你已经实现了SelectedDateChanged事件中关闭下拉,这部分可以保留,确保用户选择日期后日历自动关闭。
内容的提问来源于stack exchange,提问作者May Nguyen
相关产品推荐
相关产品推荐

