必须在WPF中的Calendar中单击两次

编辑2:谢谢大家的反馈。 我通过将其添加到我的SelectedDatesChanged事件来解决了这个问题:

Mouse.Capture(null);

当我在日历中选择日期时,我想点击“开始”按钮。 但是,我需要点击两次“开始”按钮:一次取消对焦日历,再次实际按下它。 如果在其中选择了一个项目,则鼠标离开事件不会在日历上触发,并且Keyboard.ClearFocus()也不会对其进行去焦点。

请问,每当我选择约会时,如何摆脱日历的焦点? 谢谢!

编辑:接下来单击“开始”按钮仅仅是一个例子; 如果我想选择一个文本框而我刚刚选择了一个日期,我还需要点击两次才能进入文本框。 主要问题是,一旦日历与之交互,必须在与任何其他元素交互之前单击一次。

我通过将其添加到我的SelectedDatesChanged事件来解决了这个问题:

Mouse.Capture(null);

如果您选择相同的日期,则不会引发SelectedDatesChanged ,您将看到需要单击两次的相同问题。

理想情况下,您应该挂钩到GotMouseCapture事件并从原始发件人释放鼠标捕获,以避免通过日历控件捕获任何鼠标。

 private void calendar_GotMouseCapture(object sender, MouseEventArgs e) { UIElement originalElement = e.OriginalSource as UIElement; if (originalElement != null) { originalElement.ReleaseMouseCapture(); } } 

注意 – 您可以通过使用其他答案中提到的附加属性来提取此行为。

因此, Calendar似乎专门捕获鼠标,一个选项可能是使AttachedProperty在用户点击时释放捕获

例:

 public static class CalandarHelper { public static readonly DependencyProperty SingleClickDefocusProperty = DependencyProperty.RegisterAttached("SingleClickDefocus", typeof(bool), typeof(Calendar) , new FrameworkPropertyMetadata(false, new PropertyChangedCallback(SingleClickDefocusChanged))); public static bool GetSingleClickDefocus(DependencyObject obj) { return (bool)obj.GetValue(SingleClickDefocusProperty); } public static void SetSingleClickDefocus(DependencyObject obj, bool value) { obj.SetValue(SingleClickDefocusProperty, value); } private static void SingleClickDefocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is Calendar) { Calendar calendar = d as Calendar; calendar.PreviewMouseDown += (a, b) => { if (Mouse.Captured is Calendar || Mouse.Captured is System.Windows.Controls.Primitives.CalendarItem) { Mouse.Capture(null); } }; } } } 

现在,您可以将此AttachedProperty应用于您的Calender并且一旦选择了项目,它将散焦。

完整示例:

XAML:

       

码:

 using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace WpfApplication2 { ///  /// Interaction logic for MainWindow.xaml ///  public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } public static class CalandarHelper { public static readonly DependencyProperty SingleClickDefocusProperty = DependencyProperty.RegisterAttached("SingleClickDefocus", typeof(bool), typeof(Calendar) , new FrameworkPropertyMetadata(false, new PropertyChangedCallback(SingleClickDefocusChanged))); public static bool GetSingleClickDefocus(DependencyObject obj) { return (bool)obj.GetValue(SingleClickDefocusProperty); } public static void SetSingleClickDefocus(DependencyObject obj, bool value) { obj.SetValue(SingleClickDefocusProperty, value); } private static void SingleClickDefocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is Calendar) { Calendar calendar = d as Calendar; calendar.PreviewMouseDown += (a, b) => { if (Mouse.Captured is Calendar || Mouse.Captured is System.Windows.Controls.Primitives.CalendarItem) { Mouse.Capture(null); } }; } } } } 

我在几周前遇到了同样的问题,你可以使用DatePicker,它是一个包含日历的控件,一旦用户点击一个按钮就会显示日历,当你选择一个自动关闭的日期时,DatePicker在日期时还包含一个文本框是可见的,如果需要,可以将其设为ReadOnly:这里是使用DatePicker的示例代码:

      

希望这可以帮助。

结果:

结果

释放SelectedDatesChangedGotMouseCapture所有鼠标单击将中断日历控件上月份之间的导航。 正如另一个答案所指出的,当选择相同的日期时, SelectedDatesChanged不会触发。

所以我使用了GotMouseCapture并且当点击的UIElement是一个日历日时才释放鼠标焦点。 它解决了焦点问题,并没有打破其余的控制。

 private void Calendar_GotMouseCapture(object sender, MouseEventArgs e) { UIElement originalElement = e.OriginalSource as UIElement; if (originalElement is CalendarDayButton || originalElement is CalendarItem) { originalElement.ReleaseMouseCapture(); } } 

我处理了SelectedDatesChanged事件,我正在显示MouseButtonEventArgs的属性OriginalSource。 当您选择日期时,它会显示“路径”,“矩形”等,但是当您选择实例按钮或日历以外的任何内容时,它会精确显示System.Windows.Controls.Primitives.CalendarItem。 显然,日历需要再单击一次才能将鼠标转移到另一个UIelement。 我的想法是在第一次点击日历后调用事件,以便它可以立即丢失捕获。

 public static class CalendarM { private static Button tempButton; public static bool GetRemoveProperty(DependencyObject obj) { return (bool)obj.GetValue(RemoveFocusProperty); } public static void SetRemoveProperty(DependencyObject obj, bool value) { obj.SetValue(RemoveFocusProperty, value); } public static readonly DependencyProperty RemoveFocusProperty = DependencyProperty.RegisterAttached("RemoveFocus", typeof(bool), typeof(CalendarM), new FrameworkPropertyMetadata(new PropertyChangedCallback((x, y) => { if (x is Calendar && GetRemoveProperty((DependencyObject)x)) { tempButton = new Button() { Width = 0, Height = 0 }; ((System.Windows.Controls.Panel)((FrameworkElement)x).Parent).Children.Add(tempButton); tempButton.Click += (s1, s2) => { }; ((Calendar)x).SelectedDatesChanged += CalendarM_SelectedDatesChanged; } }))); static void CalendarM_SelectedDatesChanged(object sender, SelectionChangedEventArgs e) { tempButton.RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left) { RoutedEvent = Button.MouseDownEvent }); } } 

我创建了UIelement(在这种情况下是按钮)来调用它的MouseDown事件。 我不得不将它添加到Panel(设置可见性不起作用),否则事件不允许调用自身。 现在,当您单击日历时,它会调用tempButton.Click,它会丢失捕获,当您按下按钮“GO”时,它不需要单击两次。 我知道这是一个肮脏的出路,但工作。