使用异步调用时的 WPF 输入验证问题

问题描述

我在使用异步验证时遇到验证错误的问题。

我正在使用 DevExpress 文本框,并通过验证方法使用异步调用来验证数字是否唯一。其他本地检查显示验证错误 fin,但当我进入第三步(异步)时,它没有显示错误。

我确定这是由于调用的异步性质。我已经尝试使用 async/await、Task.Runin 太多的组合,我数不清了,但仍然无法使其工作。

xaml:

<dxe:TextEdit
  EditValue="{Binding Mode=TwoWay,NotifyOnSourceUpdated=True,Path=Dto.Number,updateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}"
  InvalidValueBehavior="AllowLeaveEditor"
  IsEnabled="{Binding IsNew,UpdateSourceTrigger=PropertyChanged}"
  NullText="Enter number"
  ValidateOnTextInput="True"
  Validate="NumberOnValidate" />

xaml.cs

private void NumberOnValidate(object sender,ValidationEventArgs e)
{
  if (!((TextEdit) sender).IsEnabled)
  {
    return;
  }

  //Task.Run(async () => {
  e.ErrorContent = RequiredValidationRule.GetErrorMessage("Number",e.Value);

  if (string.IsNullOrWhiteSpace(e.ErrorContent?.ToString()))
  {
    e.ErrorContent = StringMaxlengthValidationRule.GetErrorMessage("Number",255,e.Value);

    if (string.IsNullOrWhiteSpace(e.ErrorContent?.ToString()))
    {
      var dataContext = (UpsertViewModel) DataContext;
      Task.Run(async () =>
      {
        e.ErrorContent = await Validation.IsNumberUnique(dataContext.HubConnection,dataContext.SelectedType,e.Value);
      });
    }
  }

  if (!string.IsNullOrWhiteSpace(e.ErrorContent?.ToString()))
  {
    e.IsValid = false;
  }

  //});
}

验证:

public static async Task<string> IsNumberUnique(IHubConnection hubConnection,EnumType type,object fieldValue)
{
  if (fieldValue == null || string.IsNullOrWhiteSpace(fieldValue.ToString()))
  {
    return "Cannot validate the uniqueness of the number field because it is empty.";
  }

  //Task.Run(async () =>
  //{
    try
    {
      var response = false;

      switch (type)
      {
        case EnumType.T1:
          response = await hubConnection.T1IsNumberUnique(fieldValue.ToString());

          break;

        case EnumType.T2:
          response = await hubConnection.T2IsNumberUnique(fieldValue.ToString());

          break;

        case EnumType.T3:
          response = await hubConnection.T3IsNumberUnique(fieldValue.ToString());

          break;
      }

      if (!response)
      {
        return "The number field must be unique.";
      }
    }
    catch (Exception ex)
    {
      return $"Error validating the number field for uniqueness. Exception: {ex}";
    }

    return string.Empty;
  //});

  //return string.Empty;
}

我想我已经尝试了我能想到的所有方法,但是获取异步调用的短暂延迟使得验证方法跳过响应并且它不会在 GUI 中注册。

在调试时,我可以看到在验证发生后异步响应即将到来,那么我如何对齐线程以使验证“等待”异步响应。

解决方法

Task.Run(async () =>
{
    e.ErrorContent = await Validation.IsNumberUnique(dataContext.HubConnection,dataContext.SelectedType,e.Value);
});

这段代码触发了另一个线程中的异步任务。您的原始验证线程会在您遇到时立即继续。

我猜您可以阻塞异步方法的 Result,但这会抵消异步的优势,并且会在运行时锁定 UI。

我怀疑您需要做一些很棘手的事情,例如在异步方法完成时再次引发 PropertyChanged,这将强制 WPF 再次验证,并使用某种标志来防止再次运行异步调用。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...