我有基本动作的定时器的窗口。 当计时器命中0我希望把窗口前面,以便它是可见的,而不是背后隐藏着一些其他的应用程序。
从我可以收集,我只想叫window.activate()来实现这一点,但与MVVM我的视图模型不具有窗口的引用。
我有基本动作的定时器的窗口。 当计时器命中0我希望把窗口前面,以便它是可见的,而不是背后隐藏着一些其他的应用程序。
从我可以收集,我只想叫window.activate()来实现这一点,但与MVVM我的视图模型不具有窗口的引用。
你可以去它的几种方法 - 增加了窗口的引用可能会起作用,因为视图模型不再加看法,但与此相关的,但我真的不喜欢这种做法,因为它几乎不会对夫妇您的看法您的视图模型 - 这是不是真的MVVM点
更好的方法可能是让你的视图模型引发一个事件或视图可以处理的命令。 这样的观点得到决定什么UI动作与指令/事件相关联
例如,简单地
class SomeView
{
void HandleSomeCommandOrEvent()
{
this.Activate();
}
}
当然,你怎么这样组装起来是你的,但我可能会尝试并获得路由命令发生
编辑:你真的不能“绑定”一个简单的事件,因为它是从视图模型调用。
一个简单的基于事件的例子就是将事件添加到视图模型,并直接处理它...如想象一个视图模型属性如下主窗口
public partial class MainWindow : Window
{
MainWindowViewModel ViewModel { get; set; }
public MainWindow()
{
InitializeComponent();
ViewModel = new MainWindowViewModel();
ViewModel.ShowMessage += ViewModel_ShowMessage;
this.DataContext = ViewModel;
}
void ViewModel_ShowMessage(object sender, ShowMessageEventArgs e)
{
MessageBox.Show(e.Message, "Some caption", MessageBoxButton.OK);
}
}
然后视图模型可以只触发事件:
// The view model
public class MainWindowViewModel
{
// The button click command
public RelayCommand ButtonClickCommand { get; set; }
// The event to fire
public event EventHandler<ShowMessageEventArgs> ShowMessage;
public MainWindowViewModel()
{
ButtonClickCommand = new RelayCommand(ButtonClicked);
}
void ButtonClicked(object param)
{
// This button is wired up in the view as normal and fires the event
OnShowMessage("You clicked the button");
}
// Fire the event - it's up to the view to decide how to implement this event and show a message
void OnShowMessage(string message)
{
if (ShowMessage != null) ShowMessage(this, new ShowMessageEventArgs(message));
}
}
public class ShowMessageEventArgs : EventArgs
{
public string Message { get; private set; }
public ShowMessageEventArgs(string message)
{
Message = message;
}
}
在XAML是:
<Button Command="{Binding ButtonClickCommand}">Click me!</Button>
所以按钮调用命令,而这又触发该视图(主窗口)处理,并显示一个消息的情况下。 通过这种方式,视图/ UI决定行动的基础上提出了事件的类型的过程。 当然,也可能是你的计时器,它触发事件
您可以随时下井更多地参与途径,如一些对这个问题的答案...
视图模型应该如何关闭该窗体?
但说实话,这取决于你是否真的需要它 - 一个简单的事件效果很好 - 有些人过于复杂的事情高雅的缘故,但在简单性和生产力的损害!
A“纯粹” MVVM解决方案是使用行为。 下面是一个行为Window
与Activated
属性。 该属性设置为true,将激活窗口(如果它最小化还原):
public class ActivateBehavior : Behavior<Window> {
Boolean isActivated;
public static readonly DependencyProperty ActivatedProperty =
DependencyProperty.Register(
"Activated",
typeof(Boolean),
typeof(ActivateBehavior),
new PropertyMetadata(OnActivatedChanged)
);
public Boolean Activated {
get { return (Boolean) GetValue(ActivatedProperty); }
set { SetValue(ActivatedProperty, value); }
}
static void OnActivatedChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) {
var behavior = (ActivateBehavior) dependencyObject;
if (!behavior.Activated || behavior.isActivated)
return;
// The Activated property is set to true but the Activated event (tracked by the
// isActivated field) hasn't been fired. Go ahead and activate the window.
if (behavior.AssociatedObject.WindowState == WindowState.Minimized)
behavior.AssociatedObject.WindowState = WindowState.Normal;
behavior.AssociatedObject.Activate();
}
protected override void OnAttached() {
AssociatedObject.Activated += OnActivated;
AssociatedObject.Deactivated += OnDeactivated;
}
protected override void OnDetaching() {
AssociatedObject.Activated -= OnActivated;
AssociatedObject.Deactivated -= OnDeactivated;
}
void OnActivated(Object sender, EventArgs eventArgs) {
this.isActivated = true;
Activated = true;
}
void OnDeactivated(Object sender, EventArgs eventArgs) {
this.isActivated = false;
Activated = false;
}
}
该行为需要一个参考System.Windows.Interactivity.dll
。 幸运的是,这是现在市面上的NuGet在Blend.Interactivity.Wpf包。
该行为被附加到一个XAML窗口是这样的:
<Window ...>
<i:Interaction.Behaviors>
<Behaviors:ActivateBehavior Activated="{Binding Activated, Mode=TwoWay}"/>
</i:Interaction.Behaviors>
该视图模型应该暴露一个布尔Activated
属性。 此属性设置为true,将激活窗口(除非它已被激活)。 作为额外的奖励也将恢复最小化的窗口。
我会走这条路:
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
// View
public partial class TestActivateWindow : Window
{
public TestActivateWindow() {
InitializeComponent();
Messenger.Default.Register<ActivateWindowMsg>(this, (msg) => Activate());
}
}
// View Model
public class MainViewModel: ViewModelBase
{
ICommand _activateChildWindowCommand;
public ICommand ActivateChildWindowCommand {
get {
return _activateChildWindowCommand?? (_activateChildWindowCommand = new RelayCommand(() => {
Messenger.Default.Send(new ActivateWindowMsg());
}));
}
}
}
public class ActivateWindowMsg
{
}