我有一个WPF应用程序,我正在使用MVVM。
在我的视图模型中,我有:
private string logs;
public string Logs
{
get { return logs; }
set
{
logs = value;
OnPropertyChanged("Logs");
}
}
private void ExecLoadData()
{
using (new WaitCursor())
Logs = LogFile.ReturnContent();
}
private RelayCommand loadData;
public ICommand LoadData
{
get
{
if (loadData == null)
loadData = new RelayCommand(param => this.ExecLoadData());
return loadData;
}
}
在视图中:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding LoadData}" />
</i:EventTrigger>
</i:Interaction.Triggers>
我注意到OnPropertyChanged的拍摄和页面上的数据显示之间发生了延迟。
我需要一种方法来显示等待光标到屏幕上显示的数据。
已经实现了WaitCursor()方法,但等待光标只出现,直到数据文件被加载到内存中,即在内存中加载数据之间,直到数据显示在页面上,光标保持正常。
任何提示?
编辑(在AngelWPF的帮助下最终解决方案):
private Boolean isBusy = false;
public Boolean IsBusy
{
get { return isBusy; }
set
{
if (isBusy == value)
return;
isBusy = value;
OnPropertyChanged("IsBusy");
}
}
private string logs;
public string Logs
{
get { return logs; }
set
{
logs = value;
OnPropertyChanged("Logs");
}
}
public void ExecuteBusy(DoWorkEventHandler doWorkEventHandler)
{
IsBusy = true;
var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += doWorkEventHandler;
backgroundWorker.RunWorkerCompleted += (sender, e) => { IsBusy = false; };
backgroundWorker.RunWorkerAsync();
}
protected override void ExecLoadData()
{
LoadLogs();
}
private void LoadLogs()
{
ExecuteBusy((sender, e) =>
{
Logs = LogFile.ReturnContent();
});
}
<Page.Resources>
<ut:BooleanVisibilityConverter x:Key="BooleanVisibilityConverter" />
</Page.Resources>
<Page.DataContext>
<vm:ManutencaoMonitoracaoLogsViewModel/>
</Page.DataContext>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding LoadData}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid>
<TextBox Text="{Binding Logs, Mode=OneWay}" VerticalScrollBarVisibility="Auto" IsReadOnly="True" BorderBrush="White" />
<Border BorderBrush="Black" BorderThickness="1" Background="#80DBDBDB" Grid.RowSpan="3"
Visibility="{Binding IsBusy, Converter={StaticResource BooleanVisibilityConverter}}">
<Grid>
<ct:LoadingAnimation HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
</Grid>
答案 0 :(得分:0)
您不应该在模型实现中对光标有任何引用,如何从UI调用ExecelLoadData()方法?我建议在进行调用之前更改游标状态,并在返回时重新进行
答案 1 :(得分:0)
这需要通过我们称之为AsyncWorker
的东西来编排任何繁重的功能。这是使用后台工作程序的异步命令执行。它有一个触发器标志,从视图模型启动为true,因此当任何繁重的功能被委托给它时,它会在窗口的装饰器中运行。当功能执行时,动画指示用户可能延迟的功能正在运行并且他/她应该等待。然后,当委托完成时,AsyncWorker本身会隐藏动画并将页面正确显示给用户。
http://elegantcode.com/2009/08/21/a-simple-wpf-loading-animation/
我可以想象它可以这样做......
Characteristics of `AsyncWorker`
1. It is a Control that runs an animation such as
a neverending progressing progress bar
or rotating circles etc. in the adorner of the UI.
2. It accepts the parent panel on which the waiter animation is shown.
3. It has a boolean dependency property say "StartOperation".
When this changes to true we start the animation.
When true this also begins excuting the `WorkerDelegateCommand` given below.
4. It also has a ICommand dependency property called "WorkerDelegateCommand"
This will be supplied from your `ViewModel`.
It will hold the time consuming operation as a delegate.
所以基本上当我们将AsyncWorker.StartOperation
设置为true时,我们会使用动画故事板渲染父面板的装饰器并启动后台工作程序。此后台工作程序在另一个线程上运行WorkerDelegateCommand
。因此,您的慢速操作在除UI之外的另一个线程上运行。同时异步工作者动画继续运行。当WorkerDelegateCommand
委托完成其缓慢的工作时,后台工作人员DoWork
呼叫退出并调用RunCompleted
。在此,我们将StartOperation
设置为false。
我们可以通过这种方式配置此AsyncWorker ......
<Grid>
<Button Content="Do some slow work"
Command="{Binding RunAsyncWorkerCommand}" />
<AsyncWorker
ParentPanel="{Binding RelativeSource={RelativeSource
AncestorType={x:Type Grid}}}"
StartOperation="{Binding StartSlowWork, Mode=TowWay}"
WorkerDelegateCommand="{Binding MySlowDelegateCommand}"
Visibility="Collapsed" />
</Grid>
因此,在上面的示例中,当单击按钮时,包含按钮的网格显示服务员动画并开始执行慢速操作。为此,您的DataContext和/或ViewModel需要三个属性......
1. `StartSlowWork` - A boolean flag to start AsyncWorker which is TwoWay bound.
2. `RunAsyncWorkerCommand` - Command to set the `StartSlowWork` flag to true.
3. `MySlowDelegateCommand` - Command to execute slow work.
完成此操作后,每个执行缓慢的操作都可以移动到AsyncWorker。