0

I am creating a custom user control which use a timer to count the time and run the command action in the view model finally.

Problem

When the time passed, it run the elapsed event, then execute a static command.

The fact is that when I click the refresh button, it can enter the RefreshCommand_Executed (it is expected). However, it cannot enter this function for the timer elasped event fired even then code in BeginInvoke is run (it is unexpected)...

Please help for this.

Code

-CustomControl.xaml.cs

public partial class CustomControl : UserControl
{
    public static ICommand ExecuteCommand = new RoutedCommand();

    public CustomControl()
    {
        System.Timers.Timer timer = new System.Timers.Timer();
        timer.AutoReset = true;
        timer.Interval = 60000.0;
        timer.Elapsed += (sender, e) =>
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    if (ExecuteCommand != null)
                    {
                        ExecuteCommand.Execute(sender);
                     }
                }));
        };
        timer.Start();
    }

    private void ExecuteCommand_Executed(object sender, RoutedEventArgs e)
    {
        if (ExecuteCommand != null)
        {
            ExecuteCommand.Execute(sender);
        }
    }
}

-CustomControl.xaml

<UserControl ...skip...>
    <Grid>
        <Button x:Name="refreshButton"
                Content="Refresh"
                Click="ExecuteCommand_Executed" />
    </Grid>
</UserControl>

-MainView.xaml

<UserControl ...skip...>
    <UserControl.Resources>
        <vm:MainViewModel x:Key="ViewModel" />
    </UserControl.Resources>
    <Grid cmd:RelayCommandBinding.ViewModel="{StaticResource ViewModel}">
        <cmd:RelayCommandBinding Command="ctr:CustomControl.ExecuteCommand" CommandName="RefreshCommand" />
    </Grid>
</UserControl>

-MainViewModel.cs

public class MainViewModel : NotifyPropertyChanged
{
    private ICommand refreshCommand;
    public ICommand RefreshCommand
    {
        get { return refreshCommand; }
        set { if (value != refreshCommand) { refreshCommand = value; RaisePropertyChanged("RefreshCommand"); } }
    }

    public MainViewModel()
    {
        RefreshCommand = new RelayCommand(RefreshCommand_Executed);
    }

    void RefreshCommand_Executed(object o)
    {
        //code to run
    }
}
daniel
  • 1,010
  • 6
  • 15

1 Answers1

0

Your timer is probably garbage collected. Try to keep a reference of it in your control and check if it works.

By the way, you can use a Dispatcher Timer and avoid using the dispatcher yourself.

sroll
  • 752
  • 7
  • 20
  • No, it it not garbage collected, it can enter the elapsed. The problem is RefreshCommand_Executed in viewmodel not run. And I try DispatcherTimer cannot solve the problem... – daniel Aug 13 '15 at 06:19
  • @user1179915 Ok, so I misunderstood the problem. So if I understand right: - when you click on the button, ExecuteCommand_Executed is called, the command is not null and is executed - when the timer elapsed, the lambda is executed, the BeginInvoke action is executed, but ExecuteCommand.Execute is never called. Right? by the way, why do you need a static command? can't you make it a DependencyProperty of your control? – sroll Aug 13 '15 at 06:31
  • Yes, almost all your understanding is right except that when the timer elapsed, the lambda is executed, the BeginInvoke action is executed, ExecuteCommand.Execute is called, but the RefreshCommand_Executed is never call, which mouse click can. I use static command because it is my habit XP, but if really need a reason, I can use RelayCommandBinding to make any of the view models to handle the execution. DependencyProperty requires binding, therefore only the view model of the view hosts this usercontrol to handle. Although I can it to DP, but I think static to DP would fix my problem, right? – daniel Aug 13 '15 at 10:07
  • not sure it would fix the problem... Probably you'll have to go deeper and debug the ExecuteCommand.Execute() method – sroll Aug 13 '15 at 11:17