GUI 在单击之前不响应

我有一个与这里类似的问题:WPF MVVM Light: Command.RaiseCanExecuteChanged() doesn't work,使用带有 WPF 的命令并且我的 GUI 无法工作,直到我单击屏幕中的某个位置。我不使用 MVVM Light。


我通过调用 ExternalDLL.Start() 调用外部 DLL 来执行某些操作,然后调用 GetStatus() 以了解操作是否已开始。如果我得到正确的状态作为回报,我改变了实际的行动,它必须激活我的 GUI 上的一个按钮。


在我单击某个地方之前,该按钮不会自行激活。


我检查了线程,但它似乎在同一个线程上,我试图将它放在 GUI 线程中,通过使用Application.Current.Dispatcher.BeginInvoke,但它也不起作用。


这是我的代码:


private async void StartScanCommand_Executed(object sender, ExecutedRoutedEventArgs e)

{  

    ExternalDLL.Start();  

    WaitForStarting();

}

private async void WaitForStarting()

{

    Waiting();

    Stopwatch chrono = new Stopwatch();

    chrono.Start();

    bool started = false;

    while (chrono.ElapsedMilliseconds < 20000)

    {

        if (ExternalDLL.GetStatus() != ExternalDLL.Status.Started)

        {

            await Task.Delay(100);

        }

        else

        {

            started = true;

            chrono.Stop();

            StartedAction();

            break;

        }

    }

    if (!started)

    {

        MessageBox.Show("Error");

    }

}

该Waiting()方法调用激活GUI和工作的按钮。但是StartedAction()也必须激活一个按钮,并且不起作用。


这是开始操作的代码:


private void StartedAction()

{

    _actualAction = ActualAction.DoingAction;

}

这是按钮的可以执行方法:


private void SomeButtonCommand_CanExecute(object sender, 

CanExecuteRoutedEventArgs e) 

    e.CanExecute = _actualAction == ActualAction.DoingAction; 

}

我究竟做错了什么 ?


九州编程
浏览 253回答 2
2回答

牛魔王的故事

问题很简单,当ActualAction值更改时,绑定命令的 CanExecute 状态不会重新评估。要求CommandManager.InvalidateRequerySuggested()强制重新评估。private void StartedAction(){&nbsp; &nbsp; _actualAction = ActualAction.DoingAction;&nbsp; &nbsp; CommandManager.InvalidateRequerySuggested();}

潇潇雨雨

您正在 UI 线程上进行后台工作。不要在那里做,在另一个线程中做,并使用轮询、事件或其他回调方法来更新 UI(在 UI 线程上)。例如,您可以这样做:Task.Run(() => { OtherDll.DoWork(); };这将启动外螺纹上的其他工作。如果您需要更多控制,您可以将其他 dll 的功能单独包装在一个线程中。Public Class OtherDLLThread&nbsp;{&nbsp; &nbsp; Thread _internalThread;&nbsp; &nbsp; public OtherDLLThread()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;_internalThread = new Thread(ThreadMainLoop);&nbsp; &nbsp; }&nbsp; &nbsp; public void ThreadMainLoop()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; OtherDLL.DoWork();&nbsp; &nbsp; }&nbsp; &nbsp; public static void Start()&nbsp;&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp;_internalThread.Start();&nbsp; &nbsp; }}像这样使用它:OtherDLLThread other = new OtherDLLThread();other.Start();这是另一个将代码插入 UI 线程的函数:&nbsp; &nbsp; /// <summary>&nbsp; &nbsp; ///&nbsp; &nbsp; &nbsp;Runs the action on UI thread.&nbsp; &nbsp; /// </summary>&nbsp; &nbsp; /// <param name="action">The action.</param>&nbsp; &nbsp; public static void RunOnUIThread(Action action)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; try&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (Application.Current != null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Application.Current.Dispatcher.Invoke(action);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; catch (Exception ee)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _logger.Fatal("UI Thread Code Crashed. Action detail: " + action.Method, ee);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //SystemManager.Instance.SendErrorEmailToCsaTeam("Kiosk Application Crashed", "UI Thread Code Crashed. Action detail: " + action.Method);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }像这样使用它:RunOnUITHread(() => lblStatus.Text = "Working...");
打开App,查看更多内容
随时随地看视频慕课网APP