H.B*_*.B. 29 wpf controls click mouseevent
在WPF大多数控件具有MouseUp
和MouseDown
事件(和鼠标按钮特有的变化),但不是一个简单的Click
,可马上使用的事件.如果你想使用这些事件进行类似点击的行为,你需要处理我认为有点痛苦的事件.
最明显的问题是,你不能简单地忽略MouseDown
事件,因为如果你点击启动另一个控件,它被释放了,只有处理控制MouseUp
你应该点击就会触发,而它真的不应该:两个MouseUp
及MouseDown
以上相同的控制应该发生.
所以如果有的话,我会对这个一般性问题更优雅的解决方案感兴趣.
注意:有几个很好的解决方案可以在下面看到,我选择接受Rachel的答案,因为它似乎很受欢迎,但另外我想添加以下注释:
Rachel的按钮答案非常简洁明了,但是您需要将实际控件包装在一个按钮中,在某些情况下,您可能不会真正将控件视为按钮,因为它可以被单击(例如,如果它更像是超链接),进一步你需要每次都引用一个模板.
Rick Sladkey的行为答案更直接地回答了如何模拟点击/使控件可点击的原始问题,缺点是你需要引用System.Windows.Interactivity
并喜欢Rachel的解决方案,它会夸大Xaml代码.
我的附加事件答案的优点是在Xaml-Markup方面非常接近正常的点击事件,这可以用一个属性来完成,我看到的唯一问题是代码中的事件附件没有干净地封装(如果有人知道修复此问题,请在答案中添加评论).
Rac*_*hel 17
我会使用一个Button
控件并覆盖它Button.Template
直接显示内容.
<ControlTemplate x:Key="ContentOnlyTemplate" TargetType="{x:Type Button}">
<ContentPresenter />
</ControlTemplate>
<Button Template="{StaticResource ContentOnlyTemplate}">
<Label Content="Test"/>
</Button>
Run Code Online (Sandbox Code Playgroud)
Ric*_*key 12
以下是您可以添加到任何元素的行为,以便ButtonBase.Click
使用常规按钮逻辑引发事件:
public class ClickBehavior : Behavior<FrameworkElement>
{
protected override void OnAttached()
{
AssociatedObject.MouseLeftButtonDown += (s, e) =>
{
e.Handled = true;
AssociatedObject.CaptureMouse();
};
AssociatedObject.MouseLeftButtonUp += (s, e) =>
{
if (!AssociatedObject.IsMouseCaptured) return;
e.Handled = true;
AssociatedObject.ReleaseMouseCapture();
if (AssociatedObject.InputHitTest(e.GetPosition(AssociatedObject)) != null)
AssociatedObject.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent));
};
}
}
Run Code Online (Sandbox Code Playgroud)
注意使用鼠标捕获/释放和输入命中测试检查.有了这种行为,我们可以编写这样的点击处理程序:
<Grid>
<Rectangle Width="100" Height="100" Fill="LightGreen" ButtonBase.Click="Rectangle_Click">
<i:Interaction.Behaviors>
<utils:ClickBehavior/>
</i:Interaction.Behaviors>
</Rectangle>
</Grid>
Run Code Online (Sandbox Code Playgroud)
和背后的代码:
private void Rectangle_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Code-behind: Click");
}
Run Code Online (Sandbox Code Playgroud)
很容易将其转换为所有代码隐藏; 重要的部分是捕获和点击逻辑.
如果您不熟悉行为,请安装Expression Blend 4 SDK并添加此命名空间:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Run Code Online (Sandbox Code Playgroud)
并添加System.Windows.Interactivity
到您的项目.
编辑:
以下是如何将单击行为附加到代码隐藏中的元素并为click事件添加处理程序:
void AttachClickBehaviors()
{
AttachClickBehavior(rectangle1, new RoutedEventHandler(OnAttachedClick));
}
void OnAttachedClick(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Attached: Click");
}
// Reusable: doesn't need to be in the code-behind.
static void AttachClickBehavior(FrameworkElement element, RoutedEventHandler clickHandler)
{
Interaction.GetBehaviors(element).Add(new ClickBehavior());
element.AddHandler(ButtonBase.ClickEvent, clickHandler);
}
Run Code Online (Sandbox Code Playgroud)
好吧,只是想我会玩附加事件,看看我会在哪里得到它,以下似乎在大多数情况下都有效,可以使用一些改进/调试:
public static class Extensions
{
public static readonly RoutedEvent ClickEvent = EventManager.RegisterRoutedEvent(
"Click",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(UIElement)
);
public static void AddClickHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement element = d as UIElement;
if (element != null)
{
element.MouseLeftButtonDown += new MouseButtonEventHandler(element_MouseLeftButtonDown);
element.MouseLeftButtonUp += new MouseButtonEventHandler(element_MouseLeftButtonUp);
element.AddHandler(Extensions.ClickEvent, handler);
}
}
public static void RemoveClickHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement element = d as UIElement;
if (element != null)
{
element.MouseLeftButtonDown -= new MouseButtonEventHandler(element_MouseLeftButtonDown);
element.MouseLeftButtonUp -= new MouseButtonEventHandler(element_MouseLeftButtonUp);
element.RemoveHandler(Extensions.ClickEvent, handler);
}
}
static void element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
UIElement uie = sender as UIElement;
if (uie != null)
{
uie.CaptureMouse();
}
}
static void element_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
UIElement uie = sender as UIElement;
if (uie != null && uie.IsMouseCaptured)
{
uie.ReleaseMouseCapture();
UIElement element = e.OriginalSource as UIElement;
if (element != null && element.InputHitTest(e.GetPosition(element)) != null) element.RaiseEvent(new RoutedEventArgs(Extensions.ClickEvent));
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
<TextBlock local:Extensions.Click="TextBlock_Click" Text="Test"/>
Run Code Online (Sandbox Code Playgroud)
编辑:将其更改为使用鼠标捕获而不是存储未充分清除的发件人/来源。剩下的问题是您无法在代码中添加事件 usingUIElement.AddHandler(Extensions.ClickEvent, handler)
因为这省略了引发点击事件所需的其他鼠标事件的附件(您需要Extensions.AddClickHandler(object, handler)
改用)。