在我的应用程序中,我打开一个窗口输入表单。在我的App.xaml中,我定义了以下内容:
<DataTemplate DataType="{x:Type ViewModels:EditTicketViewModel}">
<Frame>
<Frame.Content>
<Views:EditTicketView></Views:EditTicketView>
</Frame.Content>
</Frame>
</DataTemplate>
我的应用程序也有一个打开窗口的窗口服务:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DevPortal.Interfaces
{
public interface IWindowService
{
public void ShowWindow(object viewModel, bool showDialog);
}
}
实现:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using DevPortal.Interfaces;
using Syncfusion.Windows.Shared;
using Syncfusion.SfSkinManager;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace DevPortal.Services
{
public class WindowService : IWindowService
{
public void ShowWindow(object viewModel, bool showDialog)
{
var window = new ChromelessWindow();
window.ResizeMode = ResizeMode.NoResize;
SfSkinManager.SetTheme(window, new Theme("FluentDark"));
window.Content = viewModel;
window.SizeToContent = SizeToContent.WidthAndHeight;
window.Title = viewModel.GetType().GetProperty("Title").GetValue(viewModel).ToString();
window.ShowIcon = false;
if (showDialog)
{
window.ShowDialog();
} else
{
window.Show();
}
}
}
}
如何打开窗口(从MainView中的视图模型)
[RelayCommand]
private void CreateTicket()
{
App.Current.ServiceProvider.GetService<IWindowService>().ShowWindow(new EditTicketViewModel(), true);
}
从ViewModel关闭这个窗口的最好方法是什么?以前,它被用来直接创建视图,在视图的构造函数中,我将订阅视图模型中的关闭事件,但我想这并不是真正的mvc方式。我需要实现某种服务吗?谢谢!
编辑:我忘了说视图是一个页面。所以我正在创建一个以视图模型为内容的窗口,视图模型的数据模板是一个包含页面的框架。
你可以从你的窗口服务返回一个IWindow
:
public class WindowService : IWindowService
{
public IWindow ShowWindow(object viewModel, bool showDialog)
{
var window = new ChromelessWindow();
...
return window;
}
}
…然后在视图模型中简单地调用Close()
。
接口就像这样简单:
public interface IWindow
{
void Close();
}
你的ChromelessWindow
实现接口:
public partial class ChromelessWindow : Window, IWindow { ... }
…视图模型只依赖于一个接口。它仍然不知道任何关于视图或实际窗口的事情。IWindow
只是一个名字。我可以叫任何名字。
从ViewModel中关闭窗口的最干净的方法是使用附加属性。
public static class perWindowHelper
{
public static readonly DependencyProperty CloseWindowProperty = DependencyProperty.RegisterAttached(
"CloseWindow",
typeof(bool?),
typeof(perWindowHelper),
new PropertyMetadata(null, OnCloseWindowChanged));
private static void OnCloseWindowChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
{
if (!(target is Window view))
{
return;
}
if (view.IsModal())
{
view.DialogResult = args.NewValue as bool?;
}
else
{
view.Close();
}
}
public static void SetCloseWindow(Window target, bool? value)
{
target.SetValue(CloseWindowProperty, value);
}
public static bool IsModal(this Window window)
{
var fieldInfo = typeof(Window).GetField("_showingAsDialog", BindingFlags.Instance | BindingFlags.NonPublic);
return fieldInfo != null && (bool)fieldInfo.GetValue(window);
}
}
在ViewModel中创建ViewClosed属性
private bool? _viewClosed;
public bool? ViewClosed
{
get => _viewClosed;
set => Set(nameof(ViewClosed), ref _viewClosed, value);
}
,然后在视图中,使用附加属性
绑定到它<Window
...
vhelp:perWindowHelper.CloseWindow="{Binding ViewClosed}" >
在我的博客中详细介绍我对MVVM导航的看法。