Question

I have a button in an MVVM application that is hooked up to a command in the view model. The handler for the view model command does some file I/O (particularly calling File.Copy to create or overwrite an existing file).

Now, it seems that when I double-click on the button, this command handler gets called twice. Since both handlers are now trying to access the same file to copy/overwrite it at the same time, I'm getting an IOException.

Is there anyway to deal with this situation short of catching the IOException and ignoring it? This does not seem to be a guaranteed catch although there may be unrelated problems with the rest of the system that causes that to happen.

Was it helpful?

Solution

Use a value in the the ViewModel to protect the code that would be running when a click occurs. Set a value like: bool bFileIO = false;

Then in your handler function:

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

      bFileIO = false;
 }

Something like that would protect the multi-clicking from trying to run multiple times.

OTHER TIPS

The easiest way of doing this is to have your command return false in CanExecute while you're executing. This will prevent the second click from happening (as your button will be disabled). If using a 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();
        });
}

I think you should use the CanExecute of your command to control your button.

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

and the viewmodel

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;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top