拖放过程中的c#确认消息框冻结文件资源管理器

拖放过程中的c#确认消息框冻结文件资源管理器,c#,wpf,C#,Wpf,我有一个带有DataGrid的窗口,用于存储文档的对象。从文件资源管理器拖放文件时,我会将其添加到数据网格中。但是,如果数据网格已包含同名对象,则会显示一个消息框,询问用户是否要替换现有的文档 问题是,当显示消息框时,它会冻结文件资源管理器。我无法关闭、最小化等。如果文件资源管理器显示在消息框前面,我必须从任务栏中选择它。我不明白为什么要冻结文件资源管理器,以及如何修复它。任何帮助都会很棒 守则: private void MainWindow_DragEnter(object sender,

我有一个带有
DataGrid
的窗口,用于存储
文档的对象。从文件资源管理器拖放文件时,我会将其添加到
数据网格中。但是,如果
数据网格
已包含同名对象,则会显示一个
消息框
,询问用户是否要替换现有的
文档

问题是,当显示
消息框时,它会冻结文件资源管理器。我无法关闭、最小化等。如果文件资源管理器显示在
消息框前面,我必须从任务栏中选择它。我不明白为什么要冻结文件资源管理器,以及如何修复它。任何帮助都会很棒

守则:

private void MainWindow_DragEnter(object sender, DragEventArgs e)
{
    gridDragDropVisual.Visibility = Visibility.Visible;
}

private void MainWindow_DragLeave(object sender, DragEventArgs e)
{
    gridDragDropVisual.Visibility = Visibility.Collapsed;
}

private void MainWindow_Drop(object sender, DragEventArgs e)
{
    gridDragDropVisual.Visibility = Visibility.Collapsed;

    // Get dropped data
    if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
    {
        List<string> files = new List<string>();

        foreach (string obj in (string[])e.Data.GetData(DataFormats.FileDrop))
        {
            // If data is a directory
            if (Directory.Exists(obj))
            {
                // Get files in directory
                string[] detectedFiles = Directory.GetFiles(obj, "*.*", SearchOption.AllDirectories);

                // Add files to list
                files.AddRange(detectedFiles);
            }
            else // If data is files
            {
                // Add files to list
                files.Add(obj);
            }
        }

        // Add files as documents
        AddItems(files.ToArray());

        // Populate datagrid
        dataGrid.ItemsSource = documentList = Documents.Get();
    }
}

private void AddItems(string[] items)
{
    foreach (string file in items)
    {
        string fileName = file.Substring(file.LastIndexOf('\\')+1);

        // Create new document
        Document newDocument = new Document(file);

        // Get any existing document with the same name
        Document existingDocument = documentList.FirstOrDefault(objDocument => objDocument.fldName == fileName);

        if (existingDocument != null)
        {
            switch (MessageBox.Show(Application.Current.MainWindow, string.Format("There is already a document that exists with the name '{0}'.\n\nWould you like to replace it?",fileName), "", MessageBoxButton.YesNo, MessageBoxImage.Question))
            {
                case MessageBoxResult.Yes:
                {
                    // Remove existing document
                    Document.Remove(existingDocument.pkDocumentID);

                    // Add document to database
                    newDocument.Add();

                    break;
                }
            }
        }
        else
        {
            // Add document to database
            newDocument.Add();
        }
    }
    // Populate datagrid
    dataGrid.ItemsSource = documentList = Documents.Get();
}
private void主窗口\u DragEnter(对象发送方,DragEventArgs e)
{
gridDragDropVisual.Visibility=可见性.Visibility;
}
私有void主窗口\u DragLeave(对象发送方,DragEventArgs e)
{
GridDragDropVisuality.Visibility=可见性。已折叠;
}
私有void主窗口\u Drop(对象发送器,DragEventArgs e)
{
GridDragDropVisuality.Visibility=可见性。已折叠;
//获取丢弃的数据
if(例如Data.GetDataPresent(DataFormats.FileDrop,false))
{
列表文件=新列表();
foreach(字符串obj in(string[])e.Data.GetData(DataFormats.FileDrop))
{
//如果数据是一个目录
if(目录存在(obj))
{
//获取目录中的文件
字符串[]detectedFiles=Directory.GetFiles(obj,“***”,SearchOption.AllDirectories);
//将文件添加到列表中
files.AddRange(检测到的文件);
}
else//如果数据是文件
{
//将文件添加到列表中
添加文件(obj);
}
}
//将文件添加为文档
附加项(files.ToArray());
//填充数据网格
dataGrid.ItemsSource=documentList=Documents.Get();
}
}
专用void附加项(字符串[]项)
{
foreach(项目中的字符串文件)
{
字符串文件名=file.Substring(file.LastIndexOf('\\')+1);
//创建新文档
文件newDocument=新文件(文件);
//获取具有相同名称的任何现有文档
documentexistingdocument=documentList.FirstOrDefault(objDocument=>objDocument.fldName==fileName);
if(existingDocument!=null)
{
开关(MessageBox.Show(Application.Current.MainWindow,string.Format(“已有一个名为“{0}”的文档存在”。\n\n是否替换它?”,文件名),“”,MessageBoxButton.YesNo,MessageBoxImage.Question))
{
案例MessageBoxResult。是:
{
//删除现有文档
Document.Remove(existingDocument.pkDocumentID);
//将文档添加到数据库
newDocument.Add();
打破
}
}
}
其他的
{
//将文档添加到数据库
newDocument.Add();
}
}
//填充数据网格
dataGrid.ItemsSource=documentList=Documents.Get();
}

问题在于它在同一个线程中运行,因此会暂停所有其他线程。解决方案是让
MessageBox
在另一个任务中运行:

//
///表示用于使用基于任务的MessageBox的包装器。
/// 
公共静态类AdvancedMessageBox
{
/// 
///在另一个任务中显示messagebox,因此它对主线程没有影响。
/// 
公共静态void TaskBasedShow(
字符串消息,
字符串标题,
MessageBox按钮,
MessageBoxImage(图像)
{
Task.Run(()=>
{
OnRes?.Invoke(MessageBox.Show(消息、标题、按钮、图像));
});
}
public delegate void OnResult(MessageBoxResult res);
/// 
///当用户按下消息框上的按钮时(调用TaskBasedShow后),将触发。
/// 
公共静态事件OnResult OnRes;
}
实施:

public主窗口()
{
初始化组件();
AdvancedMessageBox.OnRes+=MessageBox\u OnRes;
AdvancedMessageBox.TaskBasedShow(
“我的留言”,
“我的标题”,
MessageBoxButton.YesNo,
MessageBoxImage.Question);
}
/// 
///在用户按下按钮后被触发。
/// 
///按下按钮。
私有无效MessageBox_OnRes(MessageBoxResult res)
{
//在这里实现您的逻辑
}

这完全是出于设计。D+D通知由drag源在其dispatcher线程上生成。在这种情况下,资源管理器是安全的。您的MessageBox.Show()调用被阻止,因此资源管理器无法恢复其调度程序。它将看起来冻结,无法再响应输入。您可以使用自己的Dispatcher.BeginInvoke()方法在事件处理完成后运行代码。
public MainWindow()
{
    InitializeComponent();

    AdvancedMessageBox.OnRes += MessageBox_OnRes;
    AdvancedMessageBox.TaskBasedShow(
        "My message",
        "My caption",
        MessageBoxButton.YesNo,
        MessageBoxImage.Question);
}

/// <summary>
///     Is getting triggered after the user pressed a button.
/// </summary>
/// <param name="res">The pressed button.</param>
private void MessageBox_OnRes(MessageBoxResult res)
{
    // Implement you logic here
}