3


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

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

4

3 回答 3

3

正如肯特所说,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;
            }
        };
    }
}
于 2011-01-14T05:32:29.660 回答
1

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

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

于 2011-01-13T15:56:03.370 回答
1

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

于 2018-11-20T14:29:07.440 回答