Barra de progresso indeterminada
Atualmente, tenho um botão que, quando o usuário clica nele, procura uma unidade de CD-ROM específica que está pronta e contém um arquivo. Às vezes, quando o usuário clica em um botão, o botão é pressionado e o programa fica suspenso por um tempo indeterminado até que o computador leia a unidade de CD-ROM.
Fiz minha barra de progresso, mas notei algumas coisas:
1) O programa trava / congela antes que o método que verifica as unidades de CD seja chamado. Portanto, não consigo definir a barra de progresso para exibição quando o método é chamado. Parece que o programa trava quando o botão é clicado e enquanto o usuário coloca o CD ao mesmo tempo. Como posso exibir a barra de progresso assim que o botão é clicado e o mouse ainda está pressionado / até o sistema detectar a unidade de CD?
2) Estou confuso sobre como implementar o Background Worker. Eu parecia gostar de exemplos, mas nenhum deles correspondia a uma barra de progresso indeterminada com a abordagem MVVM (No code behind).
3) Como faço para desaparecer a janela após a conclusão da operação? Atualmente, tenho um botão de cancelamento (definitivamente não é útil).
Aqui está o que eu configurei até agora. Não tem certeza de como continuar:
Barra de progresso:
<Grid>
<Border BorderBrush="Black" BorderThickness="2" CornerRadius="4" Background="#EEEEEE" HorizontalAlignment="Left" Height="110" VerticalAlignment="Top" Width="295" />
<StackPanel>
<Label x:Name="lblProgress"/>
<ProgressBar x:Name="progress" Height="25" Width="270" IsIndeterminate="True" Foreground="Green"></ProgressBar>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="225,10,0,0" RenderTransformOrigin="0.083,0.526">
<Button x:Name="btnCancel" Width="60" Content="Cancel" Command="{Binding CloseCommand}"/>
</StackPanel>
</StackPanel>
</Grid>
Eu tenho um ProgressBarViewModel que contém o comando que permite ao usuário cancelar a janela de progresso. Além disso, eu tenho outro ViewModel que preciso chamar a caixa de diálogo progressBar, mas não sei ao certo onde chamá-lo, porque se o chamar dentro do meu método, o botão ainda trava sem exibir uma barra de progresso.
Notei que se eu usar o método Button_PreviewMouseDown no codebehind, no entanto, a barra de progresso aparece corretamente quando o mouse está pressionado e o sistema exibe a barra de progresso, mas não quero usá-lo porque tenho a barra de progresso em outra exibição.
Atualmente, para o meu botão de importação, tudo o que está anexado é um comando que chama um método que pesquisa unidades por uma unidade de CD-ROM.
MainViewModel:
public ICommand ImportCDFilePathCommand
{
get
{
return new RelayCommand(ImportCDFilePath, null);
}
}
private void ImportCDFilePath()
{
// dialogService.ShowDialog("Progress", progressBarWindow); <---Does not get called until the operation is done
//Gets all the drives
DriveInfo[] allDrives = DriveInfo.GetDrives();
//checks if any CD-Rom exists in the drives
var cdRomExists = allDrives.Any(x => x.DriveType == DriveType.CDRom);
// Get all the cd roms
var cdRoms = allDrives.Where(x=>x.DriveType==DriveType.CDRom && allDrives.Any(y=>y.IsReady));
//.... There is other code that is commented out too long and not necessary
}
EDITAR:
Algumas tentativas usando o BackgroundWorker:
static BackgroundWorker _bw = new BackgroundWorker();
//constructor
MainViewModel() {
_bw.DoWork += bw_DoWork;
_bw.RunWorkerAsync("Message to worker");
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
// This is called on the worker thread
Console.WriteLine(e.Argument); // writes "Message to worker"
// Perform time-consuming task...
ImportCDFilePath();
}
Erro que recebo:
The calling thread must be STA, because many UI components require this.