在iccommand操作期间更新标签
本文关键字:更新 标签 iccommand 操作 | 更新日期: 2023-09-27 18:01:20
在WPF中,使用MVVM设计,我创建了一个屏幕,旨在通过单击按钮将大量日志加载到ListView
中。返回后,将更新标签以显示返回的日志数量。这个过程有时需要一段时间。我们的DA正在优化过程中,但同时我需要做以下更改,以指示用户搜索正在运行:
- 显示鼠标为
WaitCursor
- 更新标签文本,显示"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");
}
}
到目前为止,结果和我相关的失败尝试如下:
日志返回后,Label只显示"Searching…"。
Application.Current.Dispatcher.Invoke(new Action(() => this.LogsShowingText = "Searching..."));
返回日志后,标签上只显示"显示N条日志"。
this.LogsShowingText = string.Format("Searching...");
在搜索过程中,在和之前,标签显示"Searching…"",则返回后的日志,Label读取"显示N条日志"。与#2代码相同,位置不同
我理解这可能与UI被阻塞有关,直到Action完成,这清楚地解释了尝试1显示最后排队更新到标签,尝试2显示最后硬编码更新到标签。尝试3几乎可以工作,但是在用户单击按钮执行搜索之前,不应该更新Label。我该怎么做呢?
由于这是一个开销较大的命令,意味着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编组更改。
这将只在用户单击按钮执行命令时更新标签。