我有一个项目基于WPF和MVVM。 我的项目是基于包含内容的控制,显示了我的观点(用户控件)我想执行一个命令后视图完全装入一个精灵,我想用户看到将要执行的命令后,立即查看UI。
我试着使用:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding StartProgressCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
但在此之前我看到的视图界面中的命令被执行,它是不是我要找的。
有没有人有一个想法,我应该怎么需要实现它?
Answer 1:
这是因为,即使在技术上的观点被加载(即:所有的部件都在存储器里),您的应用程序并没有闲着呢,因此UI还没有刷新。
设置使用交互命令的触发Loaded
事件已经是很好的,因为没有更好的事件重视。
我们真的等到显示的UI,在您做这个StartProgress()
我在这里假设,这是方法的名称StartProgressCommand
点):
public void StartProgress()
{
new DispatcherTimer(//It will not wait after the application is idle.
TimeSpan.Zero,
//It will wait until the application is idle
DispatcherPriority.ApplicationIdle,
//It will call this when the app is idle
dispatcherTimer_Tick,
//On the UI thread
Application.Current.Dispatcher);
}
private static void dispatcherTimer_Tick(object sender, EventArgs e)
{
//Now the UI is really shown, do your computations
}
Answer 2:
您可以使用调度,这和优先级设置为ApplicationIdle,使其在执行时,一切都已经结束
Application.Current.Dispatcher.Invoke(
DispatcherPriority.ApplicationIdle,
new Action(() =>
{
StartProgressCommand.Invoke(args);
}));
在调度员的更多信息http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherpriority.aspx
欢呼声。 你。
Answer 3:
我们用一个定时器的解决方案 - 我也对此很可疑,但它似乎很好地工作。
public static class DispatcherExtensions
{
private static Dictionary<string, DispatcherTimer> timers =
new Dictionary<string, DispatcherTimer>();
private static readonly object syncRoot = new object();
public static void DelayInvoke(this Dispatcher dispatcher, string namedInvocation,
Action action, TimeSpan delay,
DispatcherPriority priority = DispatcherPriority.Normal)
{
lock (syncRoot)
{
RemoveTimer(namedInvocation);
var timer = new DispatcherTimer(delay, priority, (s, e) =>
{
RemoveTimer(namedInvocation);
action();
}, dispatcher);
timer.Start();
timers.Add(namedInvocation, timer);
}
}
public static void CancelNamedInvocation(this Dispatcher dispatcher, string namedInvocation)
{
lock (syncRoot)
{
RemoveTimer(namedInvocation);
}
}
private static void RemoveTimer(string namedInvocation)
{
if (!timers.ContainsKey(namedInvocation)) return;
timers[namedInvocation].Stop();
timers.Remove(namedInvocation);
}
}
然后,我们调用使用
Dispatcher.CurrentDispatcher.DelayInvoke("InitSomething",()=> {
DoSomething();
},TimeSpan.FromSeconds(1));
Answer 4:
另一种方式来做到这一点:
这个定义xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
和xmlns:mi="http://schemas.microsoft.com/expression/2010/interactions"
在你的用户控件XAML和你的项目添加Microsoft.Expression.Interactions组装。 使用CallMethodAction你的扳机,就像波纹管:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<mi:CallMethodAction TargetObject="{Binding}" MethodName="StartProgressCommand"/>
</i:EventTrigger>
</i:Interaction.Triggers>
把你的TRIGER用户控件,例如根元素里:网格。 改变你的StartProgressCommand,在你的ViewModel类,从命令老式常规方法,如:
public void StartProgressCommand()
{
/* put your program logic here*/
}
它可以准确地运行的方法每个用户控件呈现时间一次。
Answer 5:
您可以检查IsLoaded属性来看,当视图是装的形式返回false,当视图满载,这个属性成为现实。
谢谢,Rajnikant
Answer 6:
您是否尝试过绑定到ContentRendered事件? 加载的事件之后它会发生,但我不确定这是否是一个出示担保的UI线程完成绘制窗口即可。
Answer 7:
您可以在“CommandExecute法”的第一行写“的Thread.Sleep(10000)”。 使用相同的加载的触发器。
如果你不希望使用的Thread.Sleep,那么你可以去“DispatcherTimer”。 开始在你的命令定时器执行方法和转移所有的代码计时器滴答事件。 你的计时器的时间间隔设置为2秒,使用户会仙的UI。
Answer 8:
我来到这个解决方案这一个。 我想用一个布尔属性集工作的启动为真的和假的结束,以便通知后台工作的用户。
基本上,它使用
- 一个
DispatcherTimer
推出了方法之后UI根据渲染这个 - 异步方法至极将执行
Action
作为参数传递
呼叫:
this.LaunchThisWhenUiLoaded(() => { /*Stuff to do after Ui loaded here*/ });
方法 :
private DispatcherTimer dispatchTimer;
private Action ActionToExecuteWhenUiLoaded;
/// <summary>
/// Handy method to launch an Action after full UI rendering
/// </summary>
/// <param name="toExec"></param>
protected void LaunchThisWhenUiLoaded(Action toExec)
{
ActionToExecuteWhenUiLoaded = toExec;
// Call UiLoaded method when UI is loaded and rendered
dispatchTimer = new DispatcherTimer(TimeSpan.Zero, DispatcherPriority.ContextIdle, UiLoaded, Application.Current.Dispatcher);
}
/// <summary>
/// Method called after UI rendered
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected async void UiLoaded(object sender, EventArgs e)
{
this.IsBusy = true;
if (ActionToExecuteWhenUiLoaded != null)
await Task.Run(ActionToExecuteWhenUiLoaded);
dispatchTimer.Stop();
this.IsBusy = false;
}
也许不干净,但它按预期工作。
文章来源: Execute command after view is loaded WPF MVVM