Oli*_*yen 139 c# wpf mvvm mvvm-light
我想处理窗口中的"Closing"事件(当用户点击右上角的"X"按钮时),以便最终显示确认消息或/并取消关闭.
我知道如何在代码隐藏中执行此操作:订阅窗口的"Closing"事件,然后使用"CancelEventArgs.Cancel"属性.
但我正在使用MVVM,所以我不确定这是一个好方法.
我认为好的方法是将Closing事件绑定到ViewModel中的Command.
我试过了:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<cmd:EventToCommand Command="{Binding CloseCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Run Code Online (Sandbox Code Playgroud)
在我的ViewModel中使用关联的RelayCommand但它不起作用(命令的代码未执行).
dbk*_*bkk 120
我只想在View构造函数中关联处理程序:
MyWindow()
{
// Set up ViewModel, assign to DataContext etc.
Closing += viewModel.OnWindowClosing;
}
Run Code Online (Sandbox Code Playgroud)
然后将处理程序添加到ViewModel:
using System.ComponentModel;
public void OnWindowClosing(object sender, CancelEventArgs e)
{
// Handle closing logic, set e.Cancel as needed
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,除了复杂性之外,你通过使用更复杂的模式和更多的间接(5个额外的XML加号命令模式行),你几乎没有获得任何东西.
"零代码隐藏"口头禅本身并不是目标,重点是将ViewModel与View分离.即使事件绑定在View的代码隐藏中,ViewModel也不依赖于View,关闭逻辑可以进行单元测试.
Sta*_*tas 79
这段代码工作得很好:
ViewModel.cs:
public ICommand WindowClosing
{
get
{
return new RelayCommand<CancelEventArgs>(
(args) =>{
});
}
}
Run Code Online (Sandbox Code Playgroud)
在XAML中:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<command:EventToCommand Command="{Binding WindowClosing}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
Run Code Online (Sandbox Code Playgroud)
假如说
xmlns:command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL5"xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"小智 33
此选项更简单,也许适合您.在View Model构造函数中,您可以订阅主窗口关闭事件,如下所示:
Application.Current.MainWindow.Closing += new CancelEventHandler(MainWindow_Closing);
void MainWindow_Closing(object sender, CancelEventArgs e)
{
//Your code to handle the event
}
Run Code Online (Sandbox Code Playgroud)
祝一切顺利.
Axd*_*der 14
下面是根据MVVM模式,如果你不想知道在视图模型窗口(或者任何事件的)答案.
public interface IClosing
{
/// <summary>
/// Executes when window is closing
/// </summary>
/// <returns>Whether the windows should be closed by the caller</returns>
bool OnClosing();
}
Run Code Online (Sandbox Code Playgroud)
在ViewModel中添加接口和实现
public bool OnClosing()
{
bool close = true;
//Ask whether to save changes och cancel etc
//close = false; //If you want to cancel close
return close;
}
Run Code Online (Sandbox Code Playgroud)
在窗口中,我添加了Closing事件.后面的代码不会破坏MVVM模式.View可以知道viewmodel!
void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
IClosing context = DataContext as IClosing;
if (context != null)
{
e.Cancel = !context.OnClosing();
}
}
Run Code Online (Sandbox Code Playgroud)
小智 10
Geez,看起来像这里有很多代码.上面的Stas有最小努力的正确方法.这里是我的适应(使用MVVMLight但应该是识别)......哦,对PassEventArgsToCommand ="真"是绝对需要如上所示.
(感谢Laurent Bugnion http://blog.galasoft.ch/archive/2009/10/18/clean-shutdown-in-silverlight-and-wpf-applications.aspx)
... MainWindow Xaml
...
WindowStyle="ThreeDBorderWindow"
WindowStartupLocation="Manual">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<cmd:EventToCommand Command="{Binding WindowClosingCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
Run Code Online (Sandbox Code Playgroud)
在视图模型中:
///<summary>
/// public RelayCommand<CancelEventArgs> WindowClosingCommand
///</summary>
public RelayCommand<CancelEventArgs> WindowClosingCommand { get; private set; }
...
...
...
// Window Closing
WindowClosingCommand = new RelayCommand<CancelEventArgs>((args) =>
{
ShutdownService.MainWindowClosing(args);
},
(args) => CanShutdown);
Run Code Online (Sandbox Code Playgroud)
在ShutdownService中
/// <summary>
/// ask the application to shutdown
/// </summary>
public static void MainWindowClosing(CancelEventArgs e)
{
e.Cancel = true; /// CANCEL THE CLOSE - let the shutdown service decide what to do with the shutdown request
RequestShutdown();
}
Run Code Online (Sandbox Code Playgroud)
RequestShutdown看起来类似于以下内容,但basicRequestShutdown或其命名的任何内容决定是否关闭应用程序(无论如何都会快乐地关闭窗口):
...
...
...
/// <summary>
/// ask the application to shutdown
/// </summary>
public static void RequestShutdown()
{
// Unless one of the listeners aborted the shutdown, we proceed. If they abort the shutdown, they are responsible for restarting it too.
var shouldAbortShutdown = false;
Logger.InfoFormat("Application starting shutdown at {0}...", DateTime.Now);
var msg = new NotificationMessageAction<bool>(
Notifications.ConfirmShutdown,
shouldAbort => shouldAbortShutdown |= shouldAbort);
// recipients should answer either true or false with msg.execute(true) etc.
Messenger.Default.Send(msg, Notifications.ConfirmShutdown);
if (!shouldAbortShutdown)
{
// This time it is for real
Messenger.Default.Send(new NotificationMessage(Notifications.NotifyShutdown),
Notifications.NotifyShutdown);
Logger.InfoFormat("Application has shutdown at {0}", DateTime.Now);
Application.Current.Shutdown();
}
else
Logger.InfoFormat("Application shutdown aborted at {0}", DateTime.Now);
}
}
Run Code Online (Sandbox Code Playgroud)
提问者应该使用STAS答案,但对于使用棱镜且没有galasoft/mvvmlight的读者,他们可能想尝试我使用的:
在窗口或用户控件顶部的定义中,定义命名空间:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Run Code Online (Sandbox Code Playgroud)
就在这个定义之下:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<i:InvokeCommandAction Command="{Binding WindowClosing}" CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Run Code Online (Sandbox Code Playgroud)
viewmodel中的属性:
public ICommand WindowClosing { get; private set; }
Run Code Online (Sandbox Code Playgroud)
在viewmodel构造函数中附加delegatecommand:
this.WindowClosing = new DelegateCommand<object>(this.OnWindowClosing);
Run Code Online (Sandbox Code Playgroud)
最后,您希望在控件/窗口/关闭时触及您的代码:
private void OnWindowClosing(object obj)
{
//put code here
}
Run Code Online (Sandbox Code Playgroud)
我很想在 App.xaml.cs 文件中使用事件处理程序,该处理程序将允许您决定是否关闭应用程序。
例如,您可以在 App.xaml.cs 文件中包含类似以下代码的内容:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// Create the ViewModel to attach the window to
MainWindow window = new MainWindow();
var viewModel = new MainWindowViewModel();
// Create the handler that will allow the window to close when the viewModel asks.
EventHandler handler = null;
handler = delegate
{
//***Code here to decide on closing the application****
//***returns resultClose which is true if we want to close***
if(resultClose == true)
{
viewModel.RequestClose -= handler;
window.Close();
}
}
viewModel.RequestClose += handler;
window.DataContaxt = viewModel;
window.Show();
}
Run Code Online (Sandbox Code Playgroud)
然后在您的 MainWindowViewModel 代码中您可以有以下内容:
#region Fields
RelayCommand closeCommand;
#endregion
#region CloseCommand
/// <summary>
/// Returns the command that, when invoked, attempts
/// to remove this workspace from the user interface.
/// </summary>
public ICommand CloseCommand
{
get
{
if (closeCommand == null)
closeCommand = new RelayCommand(param => this.OnRequestClose());
return closeCommand;
}
}
#endregion // CloseCommand
#region RequestClose [event]
/// <summary>
/// Raised when this workspace should be removed from the UI.
/// </summary>
public event EventHandler RequestClose;
/// <summary>
/// If requested to close and a RequestClose delegate has been set then call it.
/// </summary>
void OnRequestClose()
{
EventHandler handler = this.RequestClose;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
#endregion // RequestClose [event]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
178670 次 |
| 最近记录: |