Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute command after view is loaded WPF MVVM

I have a project based WPF and MVVM. My project is based on a wizard containing a content control which shows my views (User Controls) I want to execute a command after the view is loaded completely, I would like the user to see the view UI immediately after the command will be executed.

I tried using :

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <i:InvokeCommandAction Command="{Binding StartProgressCommand}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

But the command is executed before I see the view UI and it's not what I'm looking for.

Does anyone have an idea how should I need to implement it?

like image 401
Ofir Avatar asked Oct 23 '12 08:10

Ofir


3 Answers

That's because even though technically the view is loaded (i.e: all the components are ready in memory), your app is not idle yet, and thus the UI isn't refreshed yet.

Setting a command using interaction triggers on the Loaded event is already good, as there is no better event to attach to.
Now to really wait until the UI is shown, do this in your StartProgress() (I'm assuming here that this is the name of the method that StartProgressCommand point to):

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
}
like image 119
Louis Kottmann Avatar answered Oct 30 '22 23:10

Louis Kottmann


You could use the Dispatcher for this and set the priority to ApplicationIdle so that it will on execute when everything has finished

            Application.Current.Dispatcher.Invoke(
            DispatcherPriority.ApplicationIdle,
            new Action(() =>
            {
               StartProgressCommand.Invoke(args);

            }));

more information on the dispatcher http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherpriority.aspx

cheers. ste.

like image 35
Steoates Avatar answered Oct 31 '22 00:10

Steoates


another way to do it:

define this xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" and xmlns:mi="http://schemas.microsoft.com/expression/2010/interactions" on your usercontrol XAML and add Microsoft.Expression.Interactions assembly on your project. use CallMethodAction on your trigger, just as bellow:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <mi:CallMethodAction TargetObject="{Binding}" MethodName="StartProgressCommand"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

Put the triger inside the root element of your usercontrol, e.g: grid. And change your StartProgressCommand, in your ViewModel class, from command to plain old regular Method, e.g:

public void StartProgressCommand()
{
  /* put your program logic here*/
}

It'll run the method exactly one time every time your user control rendered.

like image 28
randomguy Avatar answered Oct 30 '22 23:10

randomguy