MouseDown/Up 事件在 WPF 中无法正常工作
MouseDown/Up events not working properly in WPF
我有一个基于 ToggleButton 的自定义控件。在其构造函数中,我创建了一些 FrameworkElementFactory
类型的元素,并为其中一个元素分配了一个 EventHandler,如下所示:
button.AddHandler(Ellipse.MouseDownEvent, new MouseButtonEventHandler(Toggle));
这是我的事件处理程序:
private void Toggle(object sender, EventArgs e)
{
var active = GetTemplateChild("Active");
var button = GetTemplateChild("ToggleButton");
Storyboard sb = new Storyboard();
var ta = new ThicknessAnimation();
Storyboard.SetTargetProperty(ta, new PropertyPath("Margin"));
Storyboard.SetTarget(ta, button);
ta.Duration = TimeSpan.FromSeconds(0.2);
var da = new DoubleAnimation();
Storyboard.SetTargetProperty(da, new PropertyPath("Width"));
Storyboard.SetTarget(da, active);
da.Duration = TimeSpan.FromSeconds(0.2);
if ((bool)IsChecked)
{
ta.To = new Thickness(0);
da.To = (double)button.GetValue(Ellipse.WidthProperty);
IsChecked = !IsChecked;
}
else
{
ta.To = new Thickness(this.Width - (double)button.GetValue(Ellipse.WidthProperty), 0, 0, 0);
da.To = this.Width;
IsChecked = !IsChecked;
}
sb.Children.Add(ta);
sb.Children.Add(da);
sb.Begin();
}
但是没用。在它只工作一次的意义上不起作用。我的意思是它应该根据 IsChecked
属性 设置滑块的宽度。最初,它被设置为 false
。当我单击它时,它会按预期向右扩展。但是当我再次点击时,它并没有像预期的那样向左移动。
更令人惊讶的是它与MouseEnter
事件完美配合。 MouseDown/Up/LeftMouseButtonUp/PreviewMouseDown.....
等所有其他事件也不起作用。
如果您想在不进行大量编辑的情况下重现问题,请使用代码 here。
然后只需在 WPF 应用程序中使用它,您就会看到。
非常感谢任何帮助。
编辑: 另一个发现:它适用于右键单击和中键单击,但不适用于左键单击。想知道为什么...?? 我的鼠标工作正常。
编辑#2: Converters
在实现了几个自定义控件后,我发现了一些有趣的行为,尤其是在处理鼠标事件时。基本上,您可能 运行 遇到另一个控件,甚至可能在您的 ControlTemplate
中窃取鼠标焦点并在您获得鼠标事件之前消耗鼠标事件的情况。
问题有两种解决方法:
- 使用MousePreviewEvents,注意不要标记消费的事件
- 绑定到您希望看到更改的实际 属性
在这种特殊情况下,我会有一个 InternalIsCheckedProperty
,您可以将其绑定到 ToggleButton.IsCheckedProperty
以调用您的故事板。
MouseDown
和 MouseUp
事件由 UserControl
触发。
您应该使用事件:PreviewMouseDown
和 PreviewMouseUp
.
此外,您可以使用 MouseEnter
和 MouseLeave
事件来解决鼠标位于对象上方时的视觉反馈。
我有一个基于 ToggleButton 的自定义控件。在其构造函数中,我创建了一些 FrameworkElementFactory
类型的元素,并为其中一个元素分配了一个 EventHandler,如下所示:
button.AddHandler(Ellipse.MouseDownEvent, new MouseButtonEventHandler(Toggle));
这是我的事件处理程序:
private void Toggle(object sender, EventArgs e)
{
var active = GetTemplateChild("Active");
var button = GetTemplateChild("ToggleButton");
Storyboard sb = new Storyboard();
var ta = new ThicknessAnimation();
Storyboard.SetTargetProperty(ta, new PropertyPath("Margin"));
Storyboard.SetTarget(ta, button);
ta.Duration = TimeSpan.FromSeconds(0.2);
var da = new DoubleAnimation();
Storyboard.SetTargetProperty(da, new PropertyPath("Width"));
Storyboard.SetTarget(da, active);
da.Duration = TimeSpan.FromSeconds(0.2);
if ((bool)IsChecked)
{
ta.To = new Thickness(0);
da.To = (double)button.GetValue(Ellipse.WidthProperty);
IsChecked = !IsChecked;
}
else
{
ta.To = new Thickness(this.Width - (double)button.GetValue(Ellipse.WidthProperty), 0, 0, 0);
da.To = this.Width;
IsChecked = !IsChecked;
}
sb.Children.Add(ta);
sb.Children.Add(da);
sb.Begin();
}
但是没用。在它只工作一次的意义上不起作用。我的意思是它应该根据 IsChecked
属性 设置滑块的宽度。最初,它被设置为 false
。当我单击它时,它会按预期向右扩展。但是当我再次点击时,它并没有像预期的那样向左移动。
更令人惊讶的是它与MouseEnter
事件完美配合。 MouseDown/Up/LeftMouseButtonUp/PreviewMouseDown.....
等所有其他事件也不起作用。
如果您想在不进行大量编辑的情况下重现问题,请使用代码 here。 然后只需在 WPF 应用程序中使用它,您就会看到。
非常感谢任何帮助。
编辑: 另一个发现:它适用于右键单击和中键单击,但不适用于左键单击。想知道为什么...?? 我的鼠标工作正常。
编辑#2: Converters
在实现了几个自定义控件后,我发现了一些有趣的行为,尤其是在处理鼠标事件时。基本上,您可能 运行 遇到另一个控件,甚至可能在您的 ControlTemplate
中窃取鼠标焦点并在您获得鼠标事件之前消耗鼠标事件的情况。
问题有两种解决方法:
- 使用MousePreviewEvents,注意不要标记消费的事件
- 绑定到您希望看到更改的实际 属性
在这种特殊情况下,我会有一个 InternalIsCheckedProperty
,您可以将其绑定到 ToggleButton.IsCheckedProperty
以调用您的故事板。
MouseDown
和 MouseUp
事件由 UserControl
触发。
您应该使用事件:PreviewMouseDown
和 PreviewMouseUp
.
此外,您可以使用 MouseEnter
和 MouseLeave
事件来解决鼠标位于对象上方时的视觉反馈。