简体   繁体   English

如何在MVVM WPF的Mainwindow中加载usercontrol?

[英]How to load usercontrol in Mainwindow in MVVM WPF?

I have a MainWindow.Xaml file. 我有一个MainWindow.Xaml文件。 And one usercontrol PatientWindow.Xaml . 还有一个用户控件PatientWindow.Xaml How to load the patient window in mainwindow in MVVM architecture? 如何在MVVM体系结构的主窗口中加载患者窗口?

MainWindow.Xaml MainWindow.Xaml

<Window x:Class="PatientAdminTool.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:vm="clr-namespace:PatientAdminTool.ViewModel"
         xmlns:v="clr-namespace:PatientAdminTool.View"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        ResizeMode="CanResizeWithGrip" 
        WindowStyle="None"  
        WindowState="Normal"  
        Title="PatientAdmin Tools"           
        Height="750"
        Width="1400"
        AllowsTransparency="True" MouseLeftButtonDown="OnMouseLeftButtonDown" BorderThickness="1"  BorderBrush="#555252"  >  
    <WindowChrome.WindowChrome>
        <WindowChrome 
        CaptionHeight="0"     
          />
    </WindowChrome.WindowChrome>
</Window>

PatientWindow.xaml PatientWindow.xaml

Usercontrol window is mentioned in below 用户控制窗口在下面提到

<UserControl x:Class="PatientAdminTool.View.PatientWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:vm="clr-namespace:PatientAdminTool.ViewModel"
         xmlns:v="clr-namespace:PatientAdminTool.View"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" >

    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <DockPanel Grid.Row="0" LastChildFill="True" Height="40" Background="#646161" >
            <StackPanel DockPanel.Dock="Left" Orientation="Horizontal">
                <TextBlock Margin=" 10,5,0,0" HorizontalAlignment="Center" Text="Patients" FontSize="16"  TextAlignment="Center" VerticalAlignment="Center" Foreground="#FFFFFF"/>
            </StackPanel>
            <StackPanel Margin="10,10,0,0" DockPanel.Dock="Right" Background="Transparent"  Orientation="Vertical" HorizontalAlignment="Right" VerticalAlignment="Top" Width="50" >
                <StackPanel Background="Transparent"  Orientation="Horizontal" HorizontalAlignment="Right">
                    <Button Focusable="False" ToolTip="Close" VerticalAlignment="Center" Background="#646161" BorderThickness="0" BorderBrush="Transparent" Padding="-4" Click="Button_Click" >
                        <Button.Content>
                            <Grid Width="45" Height="23">
                                <TextBlock Foreground="White"   Text="r" FontFamily="Marlett" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                            </Grid>
                        </Button.Content>
                        <Button.Template>
                            <ControlTemplate TargetType="Button">
                                <ContentPresenter Content="{TemplateBinding Content}"/>
                            </ControlTemplate>
                        </Button.Template>

                    </Button>
                </StackPanel>
            </StackPanel>
        </DockPanel>
    </Grid>
</UserControl>

So I need to load the patient window above of main window using MVVM. 因此,我需要使用MVVM在主窗口上方加载患者窗口。 Here I need to write load event in corresponding View Model. 在这里,我需要在相应的视图模型中编写load事件。 Please help me to do this. 请帮我做到这一点。

Just add a ControlPresenter at MainWindow. 只需在MainWindow中添加ControlPresenter

<ContentPresenter Content="{Binding YouTypeHere}">
             <ContentPresenter.Resources>
                 <DataTemplate DataType="{x:Type fristViewModel1Type}">
                     <youControlForViewModel1 />
                 </DataTemplate>
                 <DataTemplate DataType="{x:Type secondViewModel2Type}">
                     <youControlForViewModel2 />
                 </DataTemplate>
            </ContentPresenter.Resources>
         </ContentPresenter>

And you could change Views via binding different VM to ContentPresenter. 您可以通过将不同的VM绑定到ContentPresenter来更改视图。

So you want to open a new child window using MVVM? 因此,您想使用MVVM打开新的子窗口吗? I assume you would open it from MainWindowViewModel. 我假设您将从MainWindowViewModel中打开它。

Solution 1: without strict MVVM 解决方案1:没有严格的MVVM

Sometimes its fine to open it directly from the ViewModel: 有时可以直接从ViewModel中打开它很好:

private void OnOpenPatientWindowCommandExecute()
{
    var o = new PatientWindow();
    o.ShowDialog(); 
}

For this you would have to change PatientWindow from UserControl to a Window . 为此,您必须将PatientWindowUserControl更改为Window

Solution 2: strict MVVM 解决方案2:严格的MVVM

The solutions following strict MVVM are a little more complex. 遵循严格的MVVM的解决方案要复杂一些。 In the solution I write here you would have to use a Service , add it to your MainWindowViewModel and bind a control from the view to a Command in the ViewModel. 在我在这里编写的解决方案中,您将必须使用Service ,将其添加到MainWindowViewModel中,然后将视图中的控件绑定到ViewModel中的Command上。 Also, its written as if you are using Dependency Injection , that's why you see the service injected in the constructor. 同样,其编写方式就像您正在使用Dependency Injection一样 ,这就是为什么您看到在构造函数中注入了服务的原因。 You can avoid this by just instantiating the service in the constructor. 您可以通过在构造函数中实例化服务来避免这种情况。

MainWindowViewModel.cs MainWindowViewModel.cs

using Prism.Wpf.Commands; // For easy commands
using PatientAdminTool.Services; // Where you put your new service

public class MainWindowViewModel
{
   private IShowDialogService _ShowDialogService;

   public MainWindowViewModel(IShowDialogService showDialogService)
   {
       _ShowDialogService = showDialogService;

       // Or do: _ShowDialogService = new ShowDialogService();
       // But that's not a good practice and won't let you test
       // this ViewModel properly.

       OpenPatientWindowCommand = new DelegateCommand(OnOpenPatientWindowCommandExecute);
   }

   public ICommand OpenPatientWindowCommand { get; private set; }

   private void OnOpenPatientWindowCommandExecute()
   {
       _ShowDialogService.ShowPatientWindow();
   }
}

Services\\IShowDialogService.cs 服务\\ IShowDialogService.cs

public interface IShowDialogService
{
    void ShowPatientWindow();

    void ShowOtherWindow();

    // ...
}

Services\\ShowDialogService.cs Services \\ ShowDialogService.cs

public class ShowDialogService : IShowDialogService
{
    public void ShowPatientWindow()
    {
        var patientWindowViewModel = new PatientWindowViewModel();
        var patientWindow = new PatientWindow();

        patientWindow.DataContext = patientWindowViewModel;

        patientWindow.ShowDialog();
    }

    public void ShowOtherWindow()
    {
        // Other window ...
    }
}

Finally, you make the connection in the View like this: 最后,您可以像这样在View中建立连接:

MainWindow.xaml MainWindow.xaml

<Window
    xmlns:vm="clr-namespace:PatientAdminTool.ViewModel">
    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <Button Command="{Binding OpenPatientCommand}">Open Patient</Button>
    </Grid>
</Window>

Haven't tried it in Visual Studio yet but that's the idea. 尚未在Visual Studio中尝试过,但这就是想法。

If it's the only thing you are going to be displaying in the same window, just put your view in there like any other control: 如果这是您将要在同一窗口中显示的唯一内容,则只需像其他控件一样将视图放在其中即可:

<Window x:Class="PatientAdminTool.MainWindow"
        xmlns:v="clr-namespace:PatientAdminTool.View"... >  
    <WindowChrome.WindowChrome>
        <WindowChrome 
        CaptionHeight="0"/>
    </WindowChrome.WindowChrome>
    <v:PatientWindow/>
</Window>

Do you have a root ViewModel for your window? 您的窗口是否有根ViewModel? If so, you can bind to a PatientViewModel: 如果是这样,您可以绑定到PatientViewModel:

<v:PatientWindow DataContext="{Binding PatientViewModel}"/>

If not, it's common to set the first DataContext to a ViewModel in the code-behind like this: 如果不是这样,通常在代码中将第一个DataContext设置为ViewModel,如下所示:

<v:PatientWindow Name="PatientWindowView"/>

and: 和:

public partial class Window
{
    public MainWindow()
    {
        InitializeComponent();
        PatientWindowView.DataContext = new PatientWindowViewModel();

    }
}

If you want to display more than one View, use a ContentPresenter like Shakra has answered. 如果要显示多个视图,请使用Shakra回答过的ContentPresenter。

If you want to open a new window, use what Alberto Cardona López has suggested. 如果要打开新窗口,请使用Alberto CardonaLópez的建议。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM