WPF:MouseEnter在按下鼠标时不能在多个按钮上工作

时间:2011-01-13 15:39:41

标签: wpf button mouseenter


我在wpf中有一个切换按钮列表,我希望用户能够通过拖动它们来切换几个按钮。为此,我为每个按钮使用了MouseEnter-Event。当我按下按钮外的鼠标按钮并开始拖动时,这确实有效。但是当我按下按钮上的鼠标按钮并开始拖动时,MouseEnter-Event仅针对第一个按钮触发,我按下了鼠标按钮(也没有触发其他任何事件,如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 个答案:

答案 0 :(得分:1)

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

听起来你想要做的就是覆盖这个默认行为,以便不捕获鼠标,但说实话,我真的无法完全按照你想要实现的目标。

答案 1 :(得分:1)

正如肯特所说,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 :(得分:0)

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