C# 删除文件目录,UI未更新

C# 删除文件目录,UI未更新,c#,wpf,xaml,user-interface,C#,Wpf,Xaml,User Interface,我试图删除一个文件目录,对于我删除的每个文件,我想用当前正在删除的文件名更新UI 以下是我在ViewModel中的代码: private void ExecuteDeleteCommand() { var files = new DirectoryInfo(BackupDirectory).GetFiles(); foreach (var file in files) { ActivityFileName = file.Name; fil

我试图删除一个文件目录,对于我删除的每个文件,我想用当前正在删除的文件名更新UI

以下是我在ViewModel中的代码:

private void ExecuteDeleteCommand()
{
    var files = new DirectoryInfo(BackupDirectory).GetFiles();

    foreach (var file in files)
    {
        ActivityFileName = file.Name;
        file.Delete();
    }
}
XAML(没有什么特别的,只是一个
TextBlock
):


发生的情况是,该目录中的文件被删除,但UI只更新迭代中最后一个文件

ActivityFileName
调用
OnPropertyChanged
,所以我知道这不是问题所在

我已经创建了一个包含大约23k个文件的目录,所以我知道在它完成时,我应该看到的不是最后一个文件


我只是不明白为什么每次调用时都不更新UI。

问题是您正在使用UI线程来完成工作。因此,在executeEleteCommand()返回之前,UI不会被更新


如果您想更新UI,那么您需要在后台线程上完成这项工作。请记住,OnPropertyChanged()调用需要调度回UI线程

使用a,但在文件删除线程中,使用
ReportProgress
方法将文件名传递回UI线程。然后,在UI线程中,订阅
ProgressChanged
事件,并检索调用
ReportProgress
期间传入的文件名。您可以使用UserState对象将文件名传递给UI线程,以便告诉用户您当前正在处理的文件。

UI线程的速度不够快,无法跟上来自delete循环的大量事件。同时,我假设用户没有试图扫描23k文件名以确保一切正常工作

如果需要受影响文件的完整审核列表,可以将这些值附加到多行文本框中,以便在处理结束时显示更改

也就是说,您可以强制重新绘制。由于您已经实现了典型的OnPropertyChanged,只需包含另一个事件,以便调度器重新绘制:

    private static readonly Action EmptyDelegate = delegate() { };

    protected void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
        }
        this.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
    }

有关详细信息,请参阅。

此操作期间UI是否完全冻结?这听起来像是操作阻塞了UI线程,应该异步完成。@David Duh!这正是问题所在。如果你把它作为答案贴出来,我会把它标记为已接受。非常感谢。其他答案似乎已经涵盖了:)奇怪的是,我找不到异步删除操作,我想知道内核中是否有什么东西阻止了这一点。理想情况下,整个方法可以是
async
,只需
等待
删除操作,但我想在这种情况下,后台工作人员是次好的选择。(我想你可以使方法
异步
(使用
任务
而不是
无效
!)并执行类似
等待任务.Factory.StartNew(()=>file.Delete());
它不会是内核级异步的,但应该会释放UI线程。)@David我最终将该方法传递给了一个后台工作人员,并按预期运行。
    private static readonly Action EmptyDelegate = delegate() { };

    protected void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
        }
        this.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
    }