编辑2:谢谢大家的反馈。我通过将其添加到我的SelectedDatesChanged事件来解决了这个问题:
Mouse.Capture(null);
当我在日历中选择日期时,我想点击“开始”按钮。但是,我需要点击两次“开始”按钮:一次取消对焦日历,再次实际按下它。如果在其中选择了一个项目,则鼠标离开事件不会在日历上触发,并且Keyboard.ClearFocus()也不会将其解除焦点。
请问,每当我选择日期时,如何摆脱日历的焦点? 谢谢!
编辑:接下来单击“开始”按钮仅仅是一个例子;如果我想选择一个文本框而我刚刚选择了一个日期,我还需要点击两次才能进入文本框。主要问题是,一旦日历与之交互,必须在与任何其他元素交互之前单击一次。
答案 0 :(得分:16)
我通过将其添加到我的SelectedDatesChanged事件来解决问题:
Mouse.Capture(null);
答案 1 :(得分:9)
如果您选择相同的日期,则 SelectedDatesChanged
不会被提出,您将看到需要点击两次的相同问题。
理想情况下,您应该挂钩 GotMouseCapture
事件并 从原始发件人发布鼠标捕获 ,以避免按日历捕获任何鼠标控制。
private void calendar_GotMouseCapture(object sender, MouseEventArgs e)
{
UIElement originalElement = e.OriginalSource as UIElement;
if (originalElement != null)
{
originalElement.ReleaseMouseCapture();
}
}
注意 - 您可以通过使用其他答案中提到的附加属性来提取此行为。
答案 2 :(得分:8)
释放SelectedDatesChanged
或GotMouseCapture
中的所有鼠标点击将打破日历控件上月份之间的导航。正如另一个答案中所指出的,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();
}
}
答案 3 :(得分:3)
所以似乎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:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:helpers="clr-namespace:WpfApplication2"
Title="MainWindow" Width="300" >
<StackPanel>
<Calendar helpers:CalandarHelper.SingleClickDefocus="True" />
<TextBox />
</StackPanel>
</Window>
代码:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
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);
}
};
}
}
}
}
答案 4 :(得分:1)
我在几周前遇到过同样的问题,你可以使用DatePicker,它是一个包含日历的控件,一旦用户点击一个按钮就会显示日历,当你选择一个自动关闭的日期时,DatePicker还包含一个文本框当日期可见时,如果需要,可以将其设为ReadOnly:这里是使用DatePicker的示例代码:
<DatePicker Name="TestDatePicker" Width="120" Height="25" >
<DatePicker.Resources>
<Style TargetType="DatePickerTextBox">
<Setter Property="IsReadOnly" Value="True"></Setter>
<Setter Property="Text" Value="Select a Date"></Setter>
</Style>
</DatePicker.Resources>
</DatePicker>
希望这有帮助。
结果:
答案 5 :(得分:1)
找到了
代码:
public void ReleaseMouse()
{
if (Mouse.Captured is CalendarItem) Mouse.Capture(null);
}
XAML:
<Calendar PreviewMouseUp="ReleaseMouse" />
来源:https://quick-geek.github.io/answers/819560/index.html
简单,似乎没有缺点:
答案 6 :(得分:0)
我处理了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”时,它不需要单击两次。我知道这是一个肮脏的出路,但工作。
<StackPanel>
<Calendar local:CalendarM.RemoveProperty="True"/>
<Button Content="Go" Click="but_Click"/>
<TextBox Text="Text"/>
</StackPanel>
</StackPanel>