System.Timers.Timer Elapsed 执行命令不适用于 RelayCommand

Posted

技术标签:

【中文标题】System.Timers.Timer Elapsed 执行命令不适用于 RelayCommand【英文标题】:System.Timers.Timer Elapsed excute command not work with RelayCommand 【发布时间】:2015-11-02 02:50:42 【问题描述】:

我正在创建一个自定义用户控件,它使用计时器来计算时间并最终在视图模型中运行命令操作。

问题

当时间过去时,它运行经过的事件,然后执行一个静态命令。

事实是当我点击刷新按钮时,它可以进入RefreshCommand_Executed(这是意料之中的)。但是,即使在 BeginInvoke 中的代码运行后,它也无法为触发的计时器超时事件进入此函数(这是意外)...

请帮忙。

代码

-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
    

【问题讨论】:

MainViewModel 负责创建计时器并响应计时器触发不是有意义吗? 我知道可以,但我的目标是创建一个用户控件... 【参考方案1】:

您的计时器可能已被垃圾回收。尝试在您的控制中保留对它的引用并检查它是否有效。

顺便说一句,您可以使用 Dispatcher Timer,避免自己使用 Dispatcher。

【讨论】:

不,它不是垃圾收集,它可以进入经过。问题是视图模型中的 RefreshCommand_Executed 未运行。我尝试 DispatcherTimer 无法解决问题... @user1179915 好的,所以我误解了这个问题。因此,如果我理解正确:-当您单击按钮时,将调用 ExecuteCommand_Execute,命令不为空并执行-当计时器经过时,执行 lambda,执行 BeginInvoke 操作,但永远不会调用 ExecuteCommand.Execute .正确的?顺便说一句,为什么你需要一个静态命令?你不能让它成为你控制的 DependencyProperty 吗? 是的,几乎你所有的理解都是对的,除了当计时器到时,执行 lambda,执行 BeginInvoke 动作,调用 ExecuteCommand.Execute,但从不调用 RefreshCommand_Executed,鼠标点击能够。我使用静态命令是因为这是我的 XP 习惯,但如果真的需要理由,我可以使用 RelayCommandBinding 来制作任何视图模型来处理执行。 DependencyProperty 需要绑定,因此只有视图的视图模型承载此用户控件来处理。虽然我可以给 DP,但我认为静态给 DP 会解决我的问题,对吧? 不确定它是否能解决问题...可能您必须更深入地调试 ExecuteCommand.Execute() 方法

以上是关于System.Timers.Timer Elapsed 执行命令不适用于 RelayCommand的主要内容,如果未能解决你的问题,请参考以下文章

System.Timers.Timer 严重不准确

使用System.Timers.Timer类实现程序定时执行

System.Timers.Timer

System.Windows.Forms.TimerSystem.Timers.TimerSystem.Threading.Timer

System.Timers.Timer 几毫秒后第二次触发

是否可以在 Timer 被处理后生成触发 System.Timers.Timer 的 Elapsed 事件的示例?