【问题标题】:RelayCommand from ViewModel & DispatchTimer来自 ViewModel 和 DispatchTimer 的 RelayCommand
【发布时间】:2014-10-30 22:09:20
【问题描述】:

下午好,

我正在尝试在视图模型中触发 ICommand...从视图模型,而不是从 UI。

该命令在 UI xaml 中可以正常工作,但是在这种不同的场景中,它不能。

private DispatcherTimer telTimer;

public RelayCommand StartT_Command { get { return new RelayCommand(Exe_StartT_Command); } }

void Exe_StartT_Command(object parameter)
{
   if (telTimer != null && telTimer.IsEnabled)
   {
      telTimer.Stop();
      return;
   }
   telTimer = new DispatcherTimer();
   telTimer.Tick += new EventHandler(TelTimerTick);
   telTimer.Interval = new TimeSpan(0, 0, 0, 0, 10);
   telTimer.Start();
}

private void TelTimerTick(object sender, EventArgs e) //Every Tick
{
        Data.Te(Td);
}

就像我说的,它在 UI 上运行良好,但是,当被调用时(见下文),它一直运行到 telTimer.Start();然后......没有。

void KeyDown(int vKey)
{
   if (vKey == 0x6A) //Num Pad * Key
   {
      this.StartT_Command.Execute(null);
   }
}

有什么想法吗??

提前致谢。

EDIT1:我检查了.IsEnabled,并启用了计时器。但是,TelTimerTick() 没有运行。

EDIT2:我没有提到 KeyDown 是从不同的线程调用的。这会对触发 TelTimerTick() 的事件产生影响吗?

【问题讨论】:

  • 是的,它必须在调度程序线程上触发,你应该得到一些异常......讨厌的黑客 App.Current.Dispatcher.BeginInvoke(new Action(ExeStartTCommand));或者只是将调度程序提供给您的虚拟机,您应该在 ViewModelBase 类中真正拥有它。

标签: c# wpf mvvm viewmodel relaycommand


【解决方案1】:

我不太确定我是否遵循,但如果你只是想从你的视图模型中调用一些命令?

正如 MvGarnagle 在他的回答中指出的那样,你每次都在分配一个新的命令,做他所做的或者:

private ICommand startCommand;
public ICommand StartTCommand
{
   get { return startCommand ?? (startCommand = new RelayCommand(ExeStartTCommand)); }
}

编辑 DispatcherTimer 电话计时器; // 未分配 无效的 ExeStartTCommand() { // 可能为空 如果 telTimer!=null && telTimer.IsEnabled) { telTimer.Stop(); 返回; } telTimer = new DispatcherTimer(); telTimer.Tick += TelTimerTick; telTimer.Interval = new TimeSpan(0, 0, 0, 0, 10); telTimer.Start(); }

private void TelTimerTick(object sender, EventArgs e) //Every Tick
{
    Data.Te(Td);
}

在您的视图模型中,只需直接调用 ExeStartTCommand,不要触发命令,没有必要这样做。 现在,如果这是一个类似于自定义控件的 DO,您将不得不触发命令,以便使用这些控件的视图会使用这些命令或更常见的路由事件。

编辑:

现在是代码

// how is this hooked up? W32 wrap?
void KeyDown(int vKey)
{
   if (vKey == 0x6A) //Num Pad * Key
     // Have the dispatchers in your viewmodelbaseclass, this is just for simplicity
     App.Current.Dispatcher.BeginInvoke(new Action(ExeStartTCommand)); 
}

您的基类中确实应该有一个 Dispatcher,它设置为您希望它运行的调度程序,并使用该属性而不是上面的那个。如果您正在处理线程问题,我需要您提供更多上下文,这里有点暗中拍摄:)

干杯,

斯蒂安

【讨论】:

  • 感谢您对语义的帮助。我已经改变了它。我仍然遇到 TelTimerTick 没有从 DispatchTimer 触发的相同问题(直接运行方法或通过 ICommand) DispatchTimer 被初始化并启动,但之后没有任何东西......在不同的线程中会搞砸吗?是的...它是来自 user32.dll 的 GetAsyncKeyState,在不同线程的循环中运行。
  • @LoganKlenner 是的,确实会搞砸,确保命令在 gui 线程上执行,如上例所示。检查您的调试输出并添加全局异常处理程序以捕获我们的错误。我对你的问题知之甚少,看看这是否是一些与 w32 相关的错误(老 c++/w32 家伙)。请记住,WinProc 属于拥有窗口。
  • 你太棒了,我的朋友。谢谢你的帮助。我不得不稍微改变一下:App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => Exe_StartT_Command(null))); 但一切都很完美。
  • 我冒昧地更改了那里的一些名称。顺便说一句,您通常应该在调用/BeginInvoke 之前检查访问权限。如果不需要,您只需调用您的方法。必须在 ViewModelBase 类中。如前所述,您将在ctor中提供您的调度程序和服务,或注入它们。静态的东西通常很糟糕,M'Kay,你不应该在不需要的时候做静态,因为它们很糟糕;)呵呵
猜你喜欢
  • 2010-10-23
  • 2021-10-25
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 2022-01-01
  • 2012-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多