WPF:当鼠标按下时,多个按钮的MouseEnter事件无效

3


我在 WPF 中有一个切换按钮列表,希望用户能够通过拖动切换多个按钮。为了实现这个功能,我使用了每个按钮的 MouseEnter 事件。当我在按钮外按下鼠标并开始拖动时,这确实有效。但是当我在一个按钮上按下鼠标并开始拖动时,MouseEnter 事件仅对我按下鼠标的第一个按钮触发(同时像 mouseover 或 mousemove 等其他事件也不会触发)。
以下是代码:

public void AddButton()
{
    ToggleButton btn = new ToggleButton();
    btn.MouseEnter += VisibilityButton_Enter;
    this.gridButtons.Children.Add(btn);
}

private void VisibilityButton_Enter(object sender, MouseEventArgs e)
{
    if (e.LeftButton == MouseButtonState.Pressed || e.RightButton == MouseButtonState.Pressed)
    {
        ToggleButton btn = sender as ToggleButton;
        btn.IsChecked = !btn.IsChecked;
    }
}

我找到了一种使用“拖放”和dragover事件的解决方案,但我认为可能有更简单的解决方案?
3个回答

3

正如Kent所提到的,ToggleButton会捕获鼠标。如果我们自己处理PreviewMouseDown事件,就可以防止这种情况发生。其余部分只需要跟踪鼠标状态,以便在单个悬停期间不要点击两次。这里是一个行为,您可以将其添加到按钮中以启用悬停点击。

首先添加此命名空间:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

并且对应于您的项目的参考文献。

然后,XAML看起来像这样(请注意RollOverBehavior):

<Grid>
    <ItemsControl>
        <ItemsControl.ItemsSource>
            <PointCollection>
                <Point/>
                <Point/>
                <Point/>
                <Point/>
                <Point/>
            </PointCollection>
        </ItemsControl.ItemsSource>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <ToggleButton Width="25" Height="25">
                    <i:Interaction.Behaviors>
                        <local:RollOverBehavior/>
                    </i:Interaction.Behaviors>
                </ToggleButton>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

这里是行为本身:

public class RollOverBehavior : Behavior<ToggleButton>
{
    bool mouseOver;
    bool clicked;

    protected override void OnAttached()
    {
        AssociatedObject.PreviewMouseLeftButtonDown += (s, e) =>
        {
            AssociatedObject.IsChecked = !AssociatedObject.IsChecked;
            e.Handled = true;
        };
        AssociatedObject.MouseEnter += (s, e) =>
        {
            mouseOver = true;
            clicked = false;
        };
        AssociatedObject.MouseLeave += (s, e) =>
        {
            mouseOver = false;
        };
        AssociatedObject.MouseMove += (s, e) =>
        {
            if (mouseOver && !clicked && e.LeftButton == MouseButtonState.Pressed)
            {
                AssociatedObject.IsChecked = !AssociatedObject.IsChecked;
                clicked = true;
            }
        };
    }
}

1
我曾经遇到过使用普通按钮时出现的同样问题。对我有效的解决方案是在PreviewMouseButtonDown事件中设置e.Handled = true(我也实现了这一点)。似乎仅通过鼠标点击,前一个操作直到释放鼠标按钮之前都没有完全处理,因此MouseEnter事件无法触发。

1
问题在于,ToggleButton 的默认行为是在单击左键时捕获鼠标。由于鼠标被捕获,所有鼠标事件都会发送到第一个 ToggleButton
听起来你想要做的是覆盖这个默认行为,使得鼠标不被捕获,但老实说我并不能完全理解你想要实现什么。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接