C# Win32事件+;WPF&x2B;MVVM

C# Win32事件+;WPF&x2B;MVVM,c#,wpf,xaml,winapi,mvvm,C#,Wpf,Xaml,Winapi,Mvvm,SystemEvents.SessionSwitch+= 新SessionSwitchEventHandler(SystemEvents\u SessionSwitch) 我正在构建一个wpf应用程序,它计算工作站锁定和解锁之间的时间 但是如果不在主窗口中添加代码,我很难实现它 我用来启动和停止计时器的代码 SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_Sessio

SystemEvents.SessionSwitch+= 新SessionSwitchEventHandler(SystemEvents\u SessionSwitch)

我正在构建一个wpf应用程序,它计算工作站锁定和解锁之间的时间 但是如果不在主窗口中添加代码,我很难实现它

我用来启动和停止计时器的代码

SystemEvents.SessionSwitch +=
                new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
private static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
        {
            if (e.Reason == SessionSwitchReason.SessionLock)
            {
                //Start Timer
            }
            else if (e.Reason == SessionSwitchReason.SessionUnlock)
            {
                //Stop Timer -> show window
            }
        }
问题是,此事件驻留在Microsoft.Win32中—我似乎无法在XAML中引用它(如果可以,我会将其连接到ICommand)

所有的MVVM专家,我该怎么办? 我要把它放在主窗口里吗? 或者我可以在XAML中引用Win32吗

还有一个附带的问题。。。 计时器逻辑-我是否将其保存在单独的类中,并将值存储在模型中?
不用说,我是MVVM的新手,MVVM背后的核心原则是单元可测试性和责任分离。这通常是通过确保ViewModel不知道其上面的层(即“视图”),也不应直接与任何特定于平台的类(即Microsoft.Win32.SystemEvents)交互来实现的

我建议的一种方法是创建自己的
ISystemEvents
接口,它只公开您希望ViewModel处理的事件。此接口的实现可以被视为“模型”层的一部分,基本上可以包装来自
Microsoft.Win32.SystemEvents
的所需事件。应用程序将“”接口作为ViewModel初始化的一部分

public interface ISystemEvents
{
    event EventHandler<SessionSwitchEventArgs> SessionSwitch;
}

//Pass this implementation to your viewmodel, via the constructor
public class MySystemEvents : ISystemEvents
{
    public event EventHandler<SessionSwitchEventArgs> SessionSwitch
    {
        add { Microsoft.Win32.SystemEvents.SessionSwitch += value; }
        remove { Microsoft.Win32.SystemEvents.SessionSwitch -= value; }
    }
}

public class MyViewModel
{
    public MyViewModel(ISystemEvents systemEvents)
    {
        //Store the instance of your object here, and subscribe to the desired events
    }
}
公共接口是系统事件
{
事件处理程序会话开关;
}
//通过构造函数将此实现传递给viewmodel
公共类MySystemEvents:isSystemEvents
{
公共事件处理程序会话开关
{
添加{Microsoft.Win32.SystemEvents.SessionSwitch+=value;}
删除{Microsoft.Win32.SystemEvents.SessionSwitch-=value;}
}
}
公共类MyViewModel
{
公共MyViewModel(ISystemEvents systemEvents)
{
//将对象的实例存储在此处,并订阅所需的事件
}
}

就我个人而言,我只是在激活/停用视图模型(术语取自Caliburn.Micro)时钩住并解开该事件。那么在视图模型中这样做应该没有问题……MVVM!=没有代码隐藏。UI逻辑在代码背后。应用程序逻辑在虚拟机中。我认为mvvm指南告诉我们,模型不应该包含特定用法的知识(我猜这是?-或者我弄错了)-尽管我确实喜欢你的答案:)我添加了一个非常简短的ISystemEvents接口实现示例:MySystemEvents。我认为你把这里的“模型”和“视图模型”混淆了。ViewModels应尽可能编程到一个接口,而不是一个具体的模型。这允许您通过提供自己的“测试”模型进行单元测试,或者在生产中使用“真实”模型。在本例中,“MySystemEvents”将是生产模型-您可以创建一个假的ISystemEvents,以测试您的ViewModel在开发过程中对它的反应。