在iccommand操作期间更新标签

本文关键字:更新 标签 iccommand 操作 | 更新日期: 2023-09-27 18:01:20

在WPF中,使用MVVM设计,我创建了一个屏幕,旨在通过单击按钮将大量日志加载到ListView中。返回后,将更新标签以显示返回的日志数量。这个过程有时需要一段时间。我们的DA正在优化过程中,但同时我需要做以下更改,以指示用户搜索正在运行:

  1. 显示鼠标为WaitCursor
  2. 更新标签文本,显示"Searching…"。

我有一个实现ICommand的类,我有WaitCursor正常工作。但是,我无法获得所需的行为来更新标签,以便在搜索运行时显示。我当前的代码:

MyScreen.xaml

<Button 
    Name="DisplayButton"
    Content="Display Logs"
    Command="{Binding DisplayLogsCommand}"
    Margin="0,64,10,0"
    VerticalAlignment="Top"
    HorizontalAlignment="Right"
    Width="112"/>
<Label 
    Content="{Binding LogsShowingText}"
    Margin="0,0,127,8"
    Foreground="#FF3C3B3B"
    HorizontalAlignment="Right"
    Width="145" Height="24"
    VerticalAlignment="Bottom"
    HorizontalContentAlignment="Right"
    FontSize="11"/>

MyScreenVM.cs

private Command displayLogsCommand;
private string logShowingText;
public Command DisplayLogsCommand
{
  get
  {
    if (this.displayLogsCommand == null)
    {
      // Attempt 3 made here.
      bool useWaitCursor = true;
      Func<bool> canExecute = () => this.ValidateFields();
      Action execute = () =>
      {
        /*
         *  TODO: Update this.LogsShowingText to read "Searching..."
         */
        // Attempt 1 and 2 made here.
        LogEntry[] entries = this.ClientConnection.GetLogs();
        this.LogsShowingText = string.Format("Showing {0} Logs", entries.Length);
        this.FilteredEntries = new ObservableCollection<LogEntry>(entries);
      };
      this.displayLogsCommand = new Command(useWaitCursor, canExecute, execute);
    }
    return this.displayLogsCommand;
  }
}
public string LogsShowingText
{
  get
  {
    return this.logsShowingText;
  }
  set
  {
    this.logsShowingText= value;
    OnPropertyChanged("LogsShowingText");
  }
}

到目前为止,结果和我相关的失败尝试如下:

  1. 日志返回后,Label只显示"Searching…"。

    Application.Current.Dispatcher.Invoke(new Action(() => this.LogsShowingText = "Searching..."));
    
  2. 返回日志后,标签上只显示"显示N条日志"。

    this.LogsShowingText = string.Format("Searching...");
    
  3. 搜索过程中,在和之前,标签显示"Searching…"",则返回后的日志,Label读取"显示N条日志"。与#2代码相同,位置不同

我理解这可能与UI被阻塞有关,直到Action完成,这清楚地解释了尝试1显示最后排队更新到标签,尝试2显示最后硬编码更新到标签。尝试3几乎可以工作,但是在用户单击按钮执行搜索之前,不应该更新Label。我该怎么做呢?

在iccommand操作期间更新标签

由于这是一个开销较大的命令,意味着UI在处理过程中会挂起,因此您应该将其转换为async命令。

public Command DisplayLogsCommand
{
  get
  {
    if (this.displayLogsCommand == null)
    {
        bool useWaitCursor = true;
        Func<bool> canExecute = () => this.ValidateFields();
        Action execute = async () =>
        {
           this.LogsShowingText = "Searching";
          // Attempt 1 and 2 made here.
          LogEntry[] entries = await Task<LogEntry[]>.Run(() => this.ClientConnection.GetLogs());
          this.LogsShowingText = string.Format("Showing {0} Logs", entries.Length);
          this.FilteredEntries = new ObservableCollection<LogEntry>(entries);
       };
      this.displayLogsCommand = new Command(useWaitCursor, canExecute, execute);
    }
    return this.displayLogsCommand;
  }
}

通过使Action委托异步,您现在可以在Action中等待。这允许您将对DataLayer的调用包装在Task中并等待它。现在,昂贵的操作正在UI线程上运行,您的标签将在前后得到适当的更新。不需要使用Dispatcher编组更改。

这将只在用户单击按钮执行命令时更新标签。