WPF MVVM:如何关闭窗口
我有一个 Button
,单击时会关闭我的窗口:
<Button x:Name="buttonOk" IsCancel="True">Ok</Button>
这很好,直到我将 Command
添加到 Button
即
<Button x:Name="buttonOk"
Command="{Binding SaveCommand}"
IsCancel="True">Ok</Button>
现在它不关闭大概是因为我正在处理命令
。我可以通过放入 EventHandler
并调用 this.Close()
来解决此问题,
<Button x:Name="buttonOk"
Click="closeWindow"
Command="{Binding SaveCommand}"
IsCancel="True">Ok</Button>
但现在我的代码中有代码,即方法 SaveCommand
>。我正在使用 MVVM 模式,SaveCommand
是我的代码后面的唯一代码。
我怎样才能以不同的方式做到这一点,以免使用隐藏代码?
I have a Button
that closes my window when it's clicked:
<Button x:Name="buttonOk" IsCancel="True">Ok</Button>
That's fine until I add a Command
to the Button
i.e.
<Button x:Name="buttonOk"
Command="{Binding SaveCommand}"
IsCancel="True">Ok</Button>
Now it doesn't close presumably because I am handling the Command
. I can fix this by putting an EventHandler
in and calling this.Close()
i.e.
<Button x:Name="buttonOk"
Click="closeWindow"
Command="{Binding SaveCommand}"
IsCancel="True">Ok</Button>
but now I have code in my code behind i.e. the method SaveCommand
. I am using the MVVM pattern and SaveCommand
is the only code in my code behind.
How can I do this differently so as not to use code behind?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(23)
我刚刚完成了一篇关于这个主题的博客文章。简而言之,使用
get
和set
访问器向 ViewModel 添加一个Action
属性。然后从View
构造函数中定义Action
。最后,在绑定命令中调用您的操作来关闭窗口。在 ViewModel 中:
以及在
View
构造函数中:最后,在任何应该关闭窗口的绑定命令中,我们可以简单地调用
这对我有用,似乎是一个相当优雅的解决方案,并为我节省了很多编码。
I just completed a blog post on this very topic. In a nutshell, add an
Action
property to your ViewModel withget
andset
accessors. Then define theAction
from yourView
constructor. Finally, invoke your action in the bound command that should close the window.In the ViewModel:
and in the
View
constructor:Finally, in whatever bound command that should close the window, we can simply invoke
This worked for me, seemed like a fairly elegant solution, and saved me a bunch of coding.
非常干净的 MVVM 方法是使用
Microsoft.Interactivity.Core
中定义的InteractionTrigger
和CallMethodAction
您将需要添加一个新的命名空间,如下所示:
您将需要 Microsoft.Xaml.Behaviours.Wpf 程序集,然后下面的 XAML 代码将起作用。
您不需要任何隐藏代码或其他任何内容,也可以调用
Window
的任何其他方法。Very clean and MVVM way is to use
InteractionTrigger
andCallMethodAction
defined inMicrosoft.Interactivity.Core
You will need to add a new namespace as below:
You will need the Microsoft.Xaml.Behaviours.Wpf assembly and then the below XAML code will work.
You don't need any code behind or anything else and can also call any other method of
Window
.正如有人评论的那样,我发布的代码对 MVVM 不友好,第二个解决方案怎么样?
第一,不是 MVVM 解决方案(我不会删除它作为参考)
XAML:
ViewModel:
第二,可能更好的解决方案:
使用附加行为
XAML
视图模型
行为类
与此类似的东西:
As someone commented, the code I have posted is not MVVM friendly, how about the second solution?
1st, not MVVM solution (I will not delete this as a reference)
XAML:
ViewModel:
2nd, probably better solution:
Using attached behaviours
XAML
View Model
Behaviour Class
Something similar to this:
我个人会使用一种行为来执行此类操作:
然后您可以将其附加到您的
Window
和Button
来完成工作:我已添加
Command
和CommandParameter
位于此处,以便您可以在Window
关闭之前运行命令。I'd personally use a behaviour to do this sort of thing:
You can then attach this to your
Window
andButton
to do the work:I've added
Command
andCommandParameter
here so you can run a command before theWindow
closes.对于小型应用程序,我使用自己的应用程序控制器来显示、关闭和处置窗口和 DataContext。它是应用程序 UI 中的中心点。
它是这样的:
以及它们从ViewModels的调用:
当然你可以在我的解决方案中找到一些限制。再说一遍:我用它来做小项目,这已经足够了。如果您有兴趣,我可以在此处或其他地方发布完整代码/
For small apps, I use my own Application Controller for showing, closing and disposing windows and DataContexts. It's a central point in UI of an application.
It's something like this:
and their invocations from ViewModels:
Of course you can find some restrictions in my solution. Again: I use it for small projects, and it's enough. If you're interested, I can post full code here or somewhere else/
我尝试以某种通用的 MVVM 方式解决此问题,但我总是发现最终会出现不必要的复杂逻辑。为了实现关闭行为,我从无代码隐藏的规则中破例,并在代码隐藏中简单地使用良好的事件:
XAML:
代码隐藏:
虽然我希望使用命令/MVVM 可以更好地支持这一点,但我只是认为没有比使用事件更简单、更清晰的解决方案了。
I've tried to resolve this issue in some generic, MVVM way, but I always find that I end up unnecessary complex logic. To achieve close behavior I have made an exception from the rule of no code behind and resorted to simply using good ol' events in code behind:
XAML:
Code behind:
Although I wish this would be better supported using commands/MVVM, I simply think that there is no simpler and more clear solution than using events.
我使用发布订阅模式来处理复杂的类依赖性:
ViewModel:
Window:
您可以利用Bizmonger.Patterns 获取 MessageBus。
消息总线
}
订阅
I use the Publish Subscribe pattern for complicated class-dependencies:
ViewModel:
Window:
You can leverage Bizmonger.Patterns to get the MessageBus.
MessageBus
}
Subscription
此任务有一个有用的行为,该行为不会破坏 MVVM,这是随 Expression Blend 3 引入的一种行为,允许 View 挂钩完全在 ViewModel 中定义的命令。
以上链接已存档至 http://code.msdn.microsoft.com/Window-Close-Attached-fef26a66#content
There is a useful behavior for this task which doesn't break MVVM, a Behavior, introduced with Expression Blend 3, to allow the View to hook into commands defined completely within the ViewModel.
Above link has been archived to http://code.msdn.microsoft.com/Window-Close-Attached-fef26a66#content
我们在 .xaml 定义中有 name 属性:
然后我们有按钮:
然后在 ViewModel 中:
然后最后是操作方法:
我使用此代码从应用程序中关闭弹出窗口。
We have the name property in the .xaml definition:
Then we have the button:
Then in the ViewModel:
Then at last, the action method:
I used this code to close a pop-up window from an application..
我在这个主题上挣扎了一段时间,最终采用了仍然与 MVVM 一致的最简单方法:让按钮执行完成所有繁重工作的命令,并让按钮的 Click 处理程序关闭窗口。
XAML
XAML.cs
SaveCommand.cs
确实,仍然存在代码隐藏,但这本身并没有什么不好。从面向对象的角度来看,对我来说最有意义的是告诉窗口自行关闭。
I struggled with this topic for some time, and eventually went with the simplest approach that is still consistent with MVVM: Have the button execute the Command that does all the heavy lifting and have the button's Click handler close the window.
XAML
XAML.cs
SaveCommand.cs
True, there is still code-behind, but there isn't anything inherently bad about that. And it makes the most sense to me, from an OO perspective, to just tell the window to close itself.
我发现自己必须在基于 .Net Core 3.0 的 WPF 应用程序上执行此操作,不幸的是,Microsoft.Xaml.Behaviors.Wpf NuGet 包中尚未正式提供行为支持。
相反,我采用了一种利用外观设计模式的解决方案。
接口:
Window:
视图模型上的标准命令属性:
控件绑定:
Command:
因为
Close()
方法已由Window
类实现,因此将外观接口应用于窗口是 UI 层中唯一需要的代码(对于这个简单的示例)。表示层中的命令避免了对视图/UI 层的任何依赖,因为当它调用外观上的Close
方法时,它不知道它在说什么。I found myself having to do this on a WPF application based on .Net Core 3.0, where unfortunately behaviour support was not yet officially available in the Microsoft.Xaml.Behaviors.Wpf NuGet package.
Instead, I went with a solution that made use of the Façade design pattern.
Interface:
Window:
Standard command property on the view model:
Control binding:
Command:
Because the
Close()
method is already implemented by theWindow
class, applying the façade interface to the window is the only required code behind in the UI layer (for this simple example). The command in the presentation layer avoids any dependencies on the view/UI layer as it has no idea what it is talking to when it calls theClose
method on the façade.在当前窗口
xaml.cs
文件中,调用以下代码:这应该可以完成任务。
它对我有用,希望对你也有用)
In your current window
xaml.cs
file, call the below code:This should do the thing.
It worked for me, hope will do the same for you )
我在 Silverlight 中有以下解决方案。也会在 WPF 中。
ChildWindowExt.cs:
ItemWindow.xaml:
ItemViewModel.cs:
ItemsViewModel.cs:
MainPage.xaml:
祝大家都有好的想法和项目;-)
I have following solution in Silverlight. Would also be in WPF.
ChildWindowExt.cs:
ItemWindow.xaml:
ItemViewModel.cs:
ItemsViewModel.cs:
MainPage.xaml:
I wish you all good ideas and projects ;-)
这可能会帮助您,使用 mvvm 关闭 wpf 窗口,后面的代码最少: rel="nofollow">http://jkshay.com/looking-a-wpf-window-using-mvvm-and-minimal-code-behind/
This might helps you, closing a wpf window using mvvm with minimal code behind: http://jkshay.com/closing-a-wpf-window-using-mvvm-and-minimal-code-behind/
我认为最简单的方法还没有被包括(几乎)。不使用添加新依赖项的行为,只需使用附加属性:
然后将其设置在对话框按钮上:
I think the most simple way has not been included already (almost). Instead of using Behaviours which adds new dependencies just use attached properties:
Then just set it on your dialog buttons:
我也必须处理这个问题,所以这是我的解决方案。这对我来说非常有用。
1.创建类 DelegateCommand
2.定义你的命令
3.在视图中绑定您的命令
4.现在窗口
就这样了,你也可以在xaml文件中绑定命令,用FindAncestor找到窗口并将其绑定到命令参数上。
I also had to deal with this problem, so here my solution. It works great for me.
1. Create class DelegateCommand
2. Define your command
3. Bind your command in the view
4. And now the window
so thats it, you can also bind the command in the xaml file and find the window with FindAncestor and bind it to the command parameter.
我一直在寻找同一问题的解决方案,发现执行以下操作效果很好。该解决方案类似于OP在他的问题中提到的内容,但有一些区别:
不需要
IsCancel
属性。代码隐藏不应关闭窗口。只需设置
DialogResult
就我而言,它首先执行后面的代码,然后查看绑定到按钮的模型命令。
背后的XAML
代码
视图模型
希望这会有所帮助。
I've been searching for a solution to the same problem and found that doing following works fine. The solution is similar to what OP has mentioned in his question with some differences:
No need of
IsCancel
property.Code behind should not close window. Just set
DialogResult
In my case it first executes code behind and then view model command bound to the button.
XAML
Code Behind
View Model
Hope this helps.
您可以重新表述这个问题,并通过这样做 - 提出另一个解决方案。
如何在 MVVM 环境中启用视图、视图模型等之间的通信?
您可以使用中介者模式。它基本上是一个通知系统。对于实际的 Mediator 实现,请通过 google 搜索或询问我,我可以通过电子邮件发送。
创建一个命令,其目的是关闭视图。
中介者将发出一个通知(令牌),
在 View 代码隐藏构造函数中监听此通知(令牌),如下所示:
You could rephrase the question, and by doing so - coming up with another solution.
How can I enable communication between views, viewmodels and whatnot in an MVVM environment?
You could use the Mediator pattern. It's basically a notification system. For the actual Mediator implementation, google for it or ask me and I can email it.
Make a Command whose purpose is to close the view.
The Mediator will raise a notification (a token)
Listen to this notification (token) like this in the View codebehind constructor:
这里没有回答在 wpf 中关闭对我有用的窗口的解决方案,所以我想我也会添加我的解决方案。
将 CloseWindow 事件添加到窗口中的按钮,如下所示。
The solution to close a window in wpf that that worked for me is not answered here so i thought i would add my solution too.
Add CloseWindow event to the button in you window as following.
简单的方法是关闭 saveComand 实现上的窗口。
使用下面的代码关闭窗口。
它将关闭子窗口。
Simple approach is close window on saveComand Implementation.
Use below code to close window.
It will close the child window.
没有任何依赖。
Without any dependencies.
其中 DialogResult 是视图模型中的 bool 属性
where DialogResult is bool property in your view model
您无需后台代码即可完成此操作。创建命令,在执行方法中调用视图模型上的“保存”方法,然后调用编辑窗口上的关闭方法,您可以通过参数传递给命令:
保存并关闭按钮XAML:
You can do it without code behind. Create command, in Execute method call "Save" method on viewmodel and after that call close method on edit window, which you can pass to the command by parameter:
Save&Close button XAML: