我一直在努力在MVVM模式中打开新窗口而不违反它的规则一个月。我已经阅读了我认为这里的每一篇文章,并观看了有关此的每一个视频,但作为一个业余程序员,我没有找到简单的解决方案来理解我。
最后,我想出了解决方案,依靠我找到的答案。有一些解决方案必须遵循的条件:
- Deputy injection friendly
1.不违反MVVM模式
1.可重复用于多个视图
1.易于使用(无需为每个窗口输入100行代码)。
1.没有严格的“DialogMVVM”等。图书馆允许。(我正处于学习阶段,所以我想了解我的代码在做什么。
- 免责声明:我不需要从对话框中获取结果,因此不包括在此处。*
请告诉我我的解决方案是否正确。
1.我使用DataTemplate制作了DialogWindow模板:
<Window x:Class="AWH.Views.DialogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewmodels="clr-namespace:AWH.ViewModels"
xmlns:views="clr-namespace:AWH.Views"
mc:Ignorable="d"
SizeToContent="WidthAndHeight">
<Window.Resources>
<DataTemplate DataType="{x:Type viewmodels:ProductAddViewModel}">
<views:ProductView/>
</DataTemplate>
</Window.Resources>
</Window>
2. IDialogService及在DialogService中的实现
public interface IDialogService
{
void ShowDialog(object viewModel);
}
public class DialogService : IDialogService
{
public void ShowDialog(object viewModel)
{
var win = new DialogWindow();
win.Content = viewModel;
win.ShowDialog();
}
}
3.从ViewModel打开窗口(本例为ProductListViewModel)
public class ProductListViewModel : ViewModelBase
{
private IDialogService _dialogService;
private IProductAddViewModel _productAddViewModel;
public ICommand AddProductCommand { get; set; }
public ProductListViewModel(IDialogService dialogService, IProductAddViewModel productAddViewModel)
{
_productAddViewModel = productAddViewModel;
_dialogService = dialogService;
AddProductCommand = new DelegateCommand(OpenAddProductDialog);
}
private void OpenAddProductDialog()
{
_dialogService.ShowDialog(_productAddViewModel);
}
}
4.在App.xaml.cs中注入依赖(我使用的是IServiceCollection)
services.AddSingleton<ProductListViewModel>();
services.AddSingleton<IProductAddViewModel, ProductAddViewModel>();
services.AddSingleton<IDialogService, DialogService>();
就是这样。如果我想的没错,我没有违反MVVM模式,因为viewmodel没有调用view,它调用的是viewmodel,WPF通过DataTemplates完成剩下的工作。
我说的对吗
编辑:当然,你需要一种方法从其他视图打开这个窗口。因此(在本例中)ProductListView.xaml(这是一个对应于ProductListViewModel的视图):
<Button Content="Add product" Margin="10 15" Padding="8 5" VerticalAlignment="Stretch" Command="{Binding AddProductCommand}" />
1条答案
按热度按时间ttvkxqim1#
在 MVVM 的上下文中,对话框是 View 组件的一个模块。遵循 MVVM 的规则,View Model 组件不允许处理控件或实现UI相关逻辑。这意味着,View Model 的类也不允许使用另一个处理控件或实现UI逻辑的类,因为这样的类将是 View 组件的一部分。
控件必须始终在 View 组件中示例化和处理。
设计模式的定义要求一个模式必须独立于任何语言、编译器或平台才能符合要求。
由于代码隐藏是一种纯语言特性(因此也是一种编译器特性),因此代码隐藏不能违反任何设计模式。
代码隐藏,即
partial
类是WPF的关键部分:并不是所有的东西都可以用XAML实现。如果你不能在XAML,依赖属性或复杂的逻辑中实现它,那么它必须在 View Model 中实现的结论是非常错误的。事实上,大多数与视图相关的框架代码都是用C#编写的。XAML主要用于布局UI:它在视觉上反映了UI的树结构,并且在可读性方面优于C#。此外,有些任务使用XAML更容易,例如创建
DataTemplate
。这只是在编写UI相关代码时,XAML优于C#的原因。XAML永远不能取代C#。你的问题的解决方案是从代码后面显示对话框,例如。通过实现点击处理程序。
为了增加灵活性,下面的示例使用
RoutedCommand
来替换单击处理程序。这样,对话框可以从定义相应
CommandBinding
(在本例中为MainWindow
)的控件的任何子控件显示:MainWindow.xaml.cs
MainWindow.xaml
ProductListView.xaml
IDialogService.cs
DialogService.cs
App.xaml.cs