【问题标题】:Handling WPF button double-click in MVVM pattern在 MVVM 模式中处理 WPF 按钮双击
【发布时间】:2013-07-08 23:44:19
【问题描述】:

我在 MVVM 应用程序中有一个按钮,它与视图模型中的命令挂钩。视图模型命令的处理程序执行一些文件 I/O(特别是调用 File.Copy 来创建或覆盖现有文件)。

现在,似乎当我双击按钮时,此命令处理程序被调用了两次。由于两个处理程序现在都试图访问同一个文件以同时复制/覆盖它,所以我得到了一个 IOException。

除了捕获 IOException 并忽略它之外,还有什么方法可以处理这种情况?尽管系统的其他部分可能存在不相关的问题导致这种情况发生,但这似乎并不能保证捕获。

【问题讨论】:

  • 你试过使用信号量吗?您可以围绕您的 I/O 代码设置它,以阻止任何额外的传入按钮点击。这不一定是解决办法。只是一个问题,直到你找到解决多次点击的方法。
  • @Alan:实际上,所有这些问题似乎都与处理双击有关。我不在乎处理双击事件,我只想忽略它。基本上,如果有一种方法可以仅在点击计数 == 1 时触发命令,而无需退出命令系统。
  • @CaptainBli:我曾考虑过使用信号量,但我希望它会更容易一些。 ://
  • 好吧我误会了,我试着回答一下

标签: wpf mvvm event-handling double-click


【解决方案1】:

在 ViewModel 中使用一个值来保护发生点击时将运行的代码。设置如下值:bool bFileIO = false;

然后在你的处理函数中:

 if (!bFileIO)
 {
      bFileIO = true;
      //file IO here

      bFileIO = false;
 }

类似的东西可以防止多次点击尝试运行多次。

【讨论】:

  • 我认为更好的解决方案是使用命令的 CanExecute 并在文件 io 期间将其更改为 false
  • 这会产生很多额外的代码。虽然我同意使用CanExecute 是解决问题的好方法。
  • 我想我必须这样做,因为我使用的是RoutedCommands
【解决方案2】:

执行此操作的最简单方法是在执行时让您的命令在 CanExecute 中返回 false。这将防止发生第二次点击(因为您的按钮将被禁用)。如果使用DelegateCommand from prism

private readonly DelegateCommand<object> copyCommand;
private bool isCopying = false;

public MyViewModel()
{
    copyCommand = new DelegateCommand<object>(
        _ => !isCopying,
        _ => 
        {
            if (isCopying) return;  // this shouldn't be required, but here for safety
            isCopying = true;
            copyCommand.RaiseCanExecuteChanged();
            // do copy
            isCopying = false;
            copyCommand.RaiseCanExecuteChanged();
        });
}

【讨论】:

    【解决方案3】:

    我认为你应该使用你的命令的 CanExecute 来控制你的按钮。

    <Button Command="{Binding WriteFileCommand}" Content="Button" Height="23" HorizontalAlignment="Left" Margin="273,194,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
    

    和视图模型

    public class MyViewModel
    {
        private bool isWritingFile = false;
    
        public DelegateCommand WriteFileCommand
        {
            get;
            private set;
        }
    
        public bool IsWritingFile
        {
            get
            {
                return isWritingFile;
            }
            set
            {
                isWritingFile = value;
                WriteFileCommand.RaiseCanExecuteChanged();
            }
        }
    
        public MyViewModel()
        {
            WriteFileCommand = new DelegateCommand(WriteFile, CanWriteFile);
        }
    
        private void WriteFile()
        {
            IsWritingFile = true;
    
            // write the file
            // FileStream stream = new FileStrem(...)
            //
    
            IsWritingFile = false;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-12
      • 2021-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多