MVVM:按钮保持事件命令

J P*_*ack 2 c# wpf mvvm

我希望能够分配两个不同CommandButton:

  • Click 事件 Command
  • Holdevent使用HoldTimeoutproperty指定保持持续时间的命令

    public static readonly DependencyProperty HoldCommandProperty =
    DependencyProperty.Register(
            "HoldCommand",
            typeof(ICommand),
            typeof(CommandButton),
            new PropertyMetadata(null,
                CommandChanged));
    
    public ICommand HoldCommand
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }
    
    Run Code Online (Sandbox Code Playgroud)

如何计算点击和保持的时间以及计算的位置?如果使用按钮的"Command"属性,我不确定处理Click事件是否正确.

结果XAML看起来应该是这样的:

<CommandButton x:Name="InputButton" 
               Command="{Binding PrimaryCommand}"
               CommandParameter="{Binding}"
               HoldCommand="{Binding SecondaryCommand}"
               HoldCommandParameters="{Binding}"
               HoldTimeout="2000"/>
Run Code Online (Sandbox Code Playgroud)

我已经阅读了如何实现双击,但这不完全是:

Aka*_*aur 5

您需要创建自定义控件并使用DispatcherTimer类对其进行计时.您可以添加另一个布尔值和命令属性来激活此行为.

控制如下:

public class SmartButton : Button
{
    private DispatcherTimer _timer;


    public int MillisecondsToWait
    {
        get { return (int)GetValue(MillisecondsToWaitProperty); }
        set { SetValue(MillisecondsToWaitProperty, value); }
    }

    public DispatcherTimer Timer
    {
        get { return _timer; }
        set { _timer = value; }
    }



    public ICommand ClickAndHoldCommand
    {
        get { return (ICommand)GetValue(ClickAndHoldCommandProperty); }
        set { SetValue(ClickAndHoldCommandProperty, value); }
    }


    public bool EnableClickHold
    {
        get { return (bool)GetValue(EnableClickHoldProperty); }
        set { SetValue(EnableClickHoldProperty, value); }
    }

    // Using a DependencyProperty as the backing store for EnableClickHold.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty EnableClickHoldProperty =
        DependencyProperty.Register("EnableClickHold", typeof(bool), typeof(SmartButton), new PropertyMetadata(false));



    // Using a DependencyProperty as the backing store for ClickAndHoldCommand.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ClickAndHoldCommandProperty =
        DependencyProperty.Register("ClickAndHoldCommand", typeof(ICommand), typeof(SmartButton), new UIPropertyMetadata(null));



    // Using a DependencyProperty as the backing store for MillisecondsToWait.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MillisecondsToWaitProperty =
        DependencyProperty.Register("MillisecondsToWait", typeof(int), typeof(SmartButton), new PropertyMetadata(0));


    public SmartButton()
    {
        this.PreviewMouseLeftButtonUp += OnPreviewMouseLeftButtonUp;
        this.PreviewMouseLeftButtonDown += OnPreviewMouseLeftButtonDown;

    }

    private void OnPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (EnableClickHold)
        {

                bool isMouseReleaseBeforeHoldTimeout = Timer.IsEnabled;
                ResetAndRemoveTimer();
                // Consider it as a mouse click 
                if (isMouseReleaseBeforeHoldTimeout && Command != null)
                {
                    Command.Execute(CommandParameter);
                }
                e.Handled = true;
        }
    }

    private void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (EnableClickHold)
        {
            Timer = new DispatcherTimer(DispatcherPriority.Normal, this.Dispatcher)
            {
                Interval = TimeSpan.FromMilliseconds(MillisecondsToWait)
            };
            Timer.Tick += Timer_Tick;
            Timer.IsEnabled = true;
            Timer.Start();
            e.Handled = true;
        }
    }

    void Timer_Tick(object sender, EventArgs e)
    {
        if(ClickAndHoldCommand != null)
        {
            this.ClickAndHoldCommand.Execute(this.CommandParameter);
        }

        ResetAndRemoveTimer();
    }

    private void ResetAndRemoveTimer()
    {
        if (Timer == null) return;
        Timer.Tick -= Timer_Tick;
        Timer.IsEnabled = false;
        Timer.Stop();
        Timer = null;
    }
}
Run Code Online (Sandbox Code Playgroud)

这个的xaml看起来应该是这样的

 <wpfMouseClick:SmartButton x:Name="MySmartButton"
                                   Width="100"
                                   Height="50"
                                   ClickAndHoldCommand="{Binding Path=MyTestCommand,
                                                                 ElementName=MyWindow}"
                                   EnableClickHold="True"
                                   MillisecondsToWait="1000">
            Click and Hold
        </wpfMouseClick:SmartButton>
Run Code Online (Sandbox Code Playgroud)