【问题标题】:WPF: MouseEnter doesn't work on several buttons when mouse is pressedWPF:按下鼠标时,MouseEnter 在多个按钮上不起作用
【发布时间】:2011-01-13 15:39:41
【问题描述】:


我在 wpf 中有一个切换按钮列表,我希望用户能够通过拖动来切换多个按钮。为此,我为每个按钮使用了 MouseEnter-Event。当我按下按钮外的鼠标按钮并开始拖动时,这确实有效。但是,当我在按钮上按下鼠标按钮并开始拖动时,仅在我按下鼠标按钮的第一个按钮上触发 MouseEnter-Event(也没有触发鼠标悬停或鼠标移动等其他事件)。
代码如下:

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;
    }
}

我找到了使用“拖放”和拖动事件的解决方案,但我认为一定有更简单的解决方案?

【问题讨论】:

    标签: wpf button mouseenter


    【解决方案1】:

    正如 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;
                }
            };
        }
    }
    

    【讨论】:

      【解决方案2】:

      问题在于ToggleButton 的默认行为是在单击鼠标左键时捕获鼠标。因为鼠标被捕获,所以所有鼠标事件都发送到第一个ToggleButton

      听起来你想要做的是覆盖这个默认行为,这样鼠标就不会被捕获,但老实说,我无法真正理解你想要实现的目标。

      【讨论】:

        【解决方案3】:

        我对普通的Buttons 也有同样的问题。对我有用的解决方案是在PreviewMouseButtonDown 事件中设置e.Handled = true(我也实现了这个)。看来,只要用鼠标向下单击,直到释放鼠标按钮才能完全处理上一个操作,因此无法引发 MouseEnter 事件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-13
          • 1970-01-01
          • 2016-09-22
          • 2014-11-14
          • 1970-01-01
          • 2011-06-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多