只有点击

时间:2018-09-08 20:26:35

标签: c# wpf

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

我通过调用ExternalDLL.Start()调用外部DLL来执行某些操作,并调用GetStatus()来了解操作是否开始。如果返回正确的状态,则更改实际操作,并且必须激活GUI上的按钮。

在我单击某处之前,该按钮不会激活自己。

我检查了线程,但似乎它在同一线程上,我尝试使用Application.Current.Dispatcher.BeginInvoke将其放在GUI线程中,但是它也没有起作用。

这是我的代码:

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; 
}

我在做什么错了?

2 个答案:

答案 0 :(得分:1)

问题很简单,当ActualAction值更改时,绑定的命令的CanExecute状态不会重新评估。

致电CommandManager.InvalidateRequerySuggested()强制进行重新评估。

private void StartedAction()
{
    _actualAction = ActualAction.DoingAction;
    CommandManager.InvalidateRequerySuggested();
}

答案 1 :(得分:-1)

您正在UI线程上进行后台工作。不要在那里做,在另一个线程中做,并使用轮询,事件或其他回调方法来更新UI(在UI线程上)。

例如,您可以这样做:

Task.Run(() => { OtherDll.DoWork(); };

这将启动外部线程上的其他工作。

如果您需要更多控制权,则可以将其他dll的功能全部包装在一个线程中。

Public Class OtherDLLThread 
{
    Thread _internalThread;

    public OtherDLLThread()
    {
         _internalThread = new Thread(ThreadMainLoop);
    }

    public void ThreadMainLoop()
    {
        OtherDLL.DoWork();
    }

    public static void Start() 
    {
       _internalThread.Start();
    }

}

像这样使用它:

OtherDLLThread other = new OtherDLLThread();
other.Start();

这是将代码添加到UI线程的另一个功能:

    /// <summary>
    ///     Runs the action on UI thread.
    /// </summary>
    /// <param name="action">The action.</param>
    public static void RunOnUIThread(Action action)
    {
        try
        {
            if (Application.Current != null)
                Application.Current.Dispatcher.Invoke(action);
        }
        catch (Exception ee)
        {
            _logger.Fatal("UI Thread Code Crashed. Action detail: " + action.Method, ee);
            //SystemManager.Instance.SendErrorEmailToCsaTeam("Kiosk Application Crashed", "UI Thread Code Crashed. Action detail: " + action.Method);
            throw;
        }
    }

像这样使用它:

RunOnUITHread(() => lblStatus.Text = "Working...");