视图被加载WPF MVVM后执行命令(Execute command after view is l

2019-08-01 19:23发布

我有一个项目基于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