如何根据MVVM结构打开新窗口

本文关键字:新窗口 窗口 何根 MVVM 结构 | 更新日期: 2023-09-27 18:16:41

下面是我的项目的视图代码。实际上当帮助按钮被点击时,它会打开一个新窗口。由于我无法访问Window对象,我不得不在View部分的后端代码中编写它,这是MVVM不喜欢的。是否有任何方式,我可以严格遵循MVVM,并从我的代码的视图模型部分打开新窗口?如果是,怎么做?因为我需要访问新窗口

VehicleForm.xaml

<Window x:Class="Seris.VehicleForm"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="VehicalForm" Height="500" Width="650"
            xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">

<WrapPanel Orientation="Vertical" Margin="10 " >
    <Label Content="Vehical No" HorizontalAlignment="Left"/>
    <TextBox Name="VehicalNo_Text" Height="23" Width="80" TextWrapping="Wrap" Text="{Binding VehicleNo_Focus, UpdateSourceTrigger=LostFocus}"  HorizontalAlignment="Left" />
    <Label Name="VehicleNoError_Label" Foreground="Red" Content="{Binding VehicleNo_Error, UpdateSourceTrigger=PropertyChanged}" Height="36" Width="186"/>
    <Label Content="Model" HorizontalAlignment="Left"/>
    <TextBox Name="Model_Text" Height="24" Width="80" TextWrapping="Wrap" Text="{Binding Model, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" />
    <Label x:Name="ModelError_Label" Foreground="Red" Content="{Binding Model_Error, UpdateSourceTrigger=PropertyChanged}" Height="36" Width="186"/>
    <Label Content="Manufacturing Date" HorizontalAlignment="Left"/>
    <DatePicker Name="ManufacturingDate_DateTime" SelectedDate="{Binding ManufacturingDate, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Width="136"/>
    <Label Name="ManufacturingDateError_Label" Foreground="Red" Content="{Binding ManufacturingDate_Error, UpdateSourceTrigger=PropertyChanged}" Height="36" Width="136"/>
    <Label Content="IU No" HorizontalAlignment="Left"/>
    <TextBox Height="23" Width="80" Name="IUNO_Text" TextWrapping="Wrap" Text="{Binding IUNo, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left"/>
        <Label Name="IUError_Label" Foreground="Red" Content="{Binding IU_Error, UpdateSourceTrigger=PropertyChanged}" Height="36" Width="186"/>
    <Label Content="Personnel" HorizontalAlignment="Left"/>
    <ComboBox x:Name="Personnel_Combo" SelectedValue="{Binding PersonnelNameSelected, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding PersonnelName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Width="126"/>
    <Separator Height="20" RenderTransformOrigin="0.5,0.5" Width="16"/>
    <Button Name="Save_Button" Command="{Binding SaveButton_Command}" Content="Save" Width="66"/>
    <Button Name="Replace_Button" CommandParameter="replace" IsEnabled="{Binding isEnableReplaceButton, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Command="{Binding ReplaceButton_Command}" Content="Replace" Width="66"/>
    <Button Name="Remove_Button" CommandParameter="replace" IsEnabled="{Binding isEnableReplaceButton, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Command="{Binding RemoveButton_Command}" Content="Remove" Width="66"/>

    <Label x:Name="Error_Label" Content="{Binding ErrorMessage, UpdateSourceTrigger=PropertyChanged}" Foreground="Red" HorizontalAlignment="Left" Height="41" Width="137"/>
    <ListView Name ="Grid" Height="294" Width="371" >
        <DataGrid Name="DG" ItemsSource="{Binding ListItems, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedRow, Mode=TwoWay}" GridLinesVisibility="None" IsReadOnly="True" AutoGenerateColumns="False" BorderThickness="0">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Vehical No" Binding="{Binding VehicalNo}"/>
                <DataGridTextColumn Header="Model" Binding="{Binding Model}" />
                <DataGridTextColumn Header="ManufacturingDate" Binding="{Binding ManufacturingDate}" />
                <DataGridTextColumn Header="IUNo" Binding="{Binding IUNo}" />
                <DataGridTextColumn Header="Personnel" Binding="{Binding PersonnelNameSelected}" />
                <DataGridTextColumn Header="Unique No" Binding="{Binding UniqueNo}"/>
            </DataGrid.Columns>
        </DataGrid>
    </ListView>
    <TextBlock Name="Preview" Text="{Binding EditText, UpdateSourceTrigger=PropertyChanged}"/>
    <ProgressBar Name="Progressbar" Minimum="0" Maximum="100" Value="{Binding Progress, UpdateSourceTrigger=PropertyChanged}" Height="11"/>
    <TextBlock Text="{Binding ElementName=Progressbar, Path=Value, StringFormat={}{0:0}%}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    <Button Name="Help" Visibility="{Binding HelpVisibility, UpdateSourceTrigger=PropertyChanged}" CommandParameter="help" Height="50" Width="50" Click="Help_Click" HorizontalAlignment="Right">
        <Image Height="45" Width="45" Source="../Images/help.jpg" HorizontalAlignment="Left"/>
    </Button>
</WrapPanel>
</Window>

VehicleForm.xaml.cs

using Seris.ViewModels;
using Seris.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Seris
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class VehicleForm : Window
{
    public VehicleForm()
    {
        this.DataContext = new VehicleMainViewModel();
        this.Show();
        InitializeComponent();
    }
    private void Help_Click(object sender, RoutedEventArgs e)
    {
        Help helpWindow = new Help();
        helpWindow.Show();
    }
}
}

如何根据MVVM结构打开新窗口

我认为你应该问问自己为什么要使用MVVM,你想让它为你做什么,它将解决/避免什么问题。不要仅仅因为你应该这么做就去做MVVM。

我不认为在这种情况下使用代码隐藏是错误的。MVVM的目的不是拥有尽可能短的.xaml.cs文件。

目的是:

  • 视图逻辑(VM)的可测试性,不需要涉及视图。
  • 关注点分离:视图定义用户界面,视图模型通过绑定、转换器等定义用户界面和业务逻辑之间的中介。ViewModel不需要知道View,它们可以分开开发。

在后面的代码中打开窗口是否错过了这些目的?

  • 可测试性:你应该测试什么?调用"Show()"?
  • 关注点分离:我认为你可以更好地分离在代码后打开窗口,而不是VM以任何方式知道新窗口。如果新窗口应该有一些主数据上下文的细节作为数据上下文,VM应该将其作为属性提供。