Я пытался найти решение для этого, но на данный момент ничего, что я нашел, не сделал щелчок.Я начинаю с WPF, так что, возможно, я просто пропустил какой-то очевидный ответ, но я был бы очень признателен за ответ.Это ситуация:
Мое приложение структурировано с использованием MVVM.Его основной функционал вызывается с кнопки.После вызова он перебирает все файлы в указанном каталоге и выполняет некоторое переименование.Делая этот цикл, я хотел показать индикатор выполнения, показывающий, сколько файлов было переименовано из общего количества.Значение прогресса - это свойство, связанное с элементом управления Progressbar
. Мне удалось только асинхронно обновлять индикатор выполнения;в противном случае он останется пустым до завершения процесса.Сейчас он работает с BackgroundWorker .
_bgWorker.DoWork += (s, e) =>
{
RenamingMethod();
};
...
RenamingMethodCommand = new RelayCommand(_ =>_bgWorker.RunWorkerAsync());
. Для выполнения переименования в имени файла ожидается хеш.Этот хэш будет преобразован во введенное пользователем значение, если оно найдено, в противном случае должно появиться окно с просьбой ввести его.
Это окно невозможно отобразить в MTAThread (Я использую ShowDialog , я не нашел другого способа заставить его появиться), и поэтому я не могу вызвать его из асинхронных методов в моем главном окне.Единственный способ заставить его работать - это вызвать все внутри RenamingMethod следующим образом:
public void RenamingMethod()
{
Application.Current.Dispatcher.Invoke((Action)delegate
{
//code for renaming
}
}
На этом этапе индикатор выполнения обновляется только в тот момент, когда я закрываю всплывающее окно.,Затем он остается на том же значении, пока не откроется и не закроется новое окно.
Я хотел бы открыть всплывающее окно из асинхронного метода, который обновляет индикатор выполнения, поэтому развитие этого процесса происходит плавно, ион останавливается при открытии нового окна.Или возможность синхронного обновления индикатора выполнения, вероятно, также будет работать.
Вот код более подробно:
public void RenameMethod()
{
Application.Current.Dispatcher.Invoke((Action)delegate
{
IEnumerable<string> files = Directory.EnumerateFiles(
OriginMediaFolder,
"*.*",
SearchOption.AllDirectories).
Where(name => name.EndsWith(".jpg") || name.EndsWith(".mp4"));
int numberOfFiles = files.Count();
float fileNumber = 0;
foreach (string file in files)
{
MoveAndRenameFile(file);
ProgressValue = (int)(100 * (fileNumber++ / numberOfFiles));
}
});
}
public void MoveAndRenameFile(string file)
{
//Name structure: path/1234567891234567-hash.ext
string fileName = Regex.Match(file, @"[^\/\\]+\.",RegexOptions.RightToLeft).
Value.TrimEnd('.');
string date = fileName.Substring(0, 16);
string hash = fileName.Substring(17);
if (!HashToName(hash, out string gameName))
{
var gameNamingWindow = GetNewNameFromUser(hash);
}
string extension = Regex.Match(file, @"\..+\Z", RegexOptions.RightToLeft).Value;
if (!Directory.Exists(DestinationMediaFolder + "/" + gameName))
Directory.CreateDirectory(DestinationMediaFolder + "/" + gameName);
File.Move(file, DestinationMediaFolder + "/" + gameName + "/" + date + extension);
}
public string GetNewNameFromUser(string hash)
{
var gameNamingWindow = new NewGameWindow.MainWindow(OriginMediaFolder, hash);
if (gameNamingWindow.ShowDialog().Value)
{
string gameName = gameNamingWindow.Result;
NameHashes.Add(new NameHash
{
GameName = gameName,
Hash = hash
});
return gameName;
}
return hash;
}