如何在MMVM WPF中的主窗口中打开子窗口

时间:2017-01-13 11:07:42

标签: c# wpf mvvm

我有3个屏幕

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"
         >
    <Window.DataContext>
        <vm:MainViewModel></vm:MainViewModel>    
    </Window.DataContext>
    <WindowChrome.WindowChrome>
        <WindowChrome 
        CaptionHeight="0"/>
    </WindowChrome.WindowChrome>
    <ContentControl >
        <v:PatientWindow DataContext="{Binding PatientVM}"/>
    </ContentControl>
</Window>

PatientWindow.xaml

<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" >
    <UserControl.DataContext>
        <vm:PatientSelectorVM/>
    </UserControl.DataContext>
    <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" Command="{Binding CloseCommand,Mode=TwoWay}">
                            <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>
        <ContentControl Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
            <v:PatientSelector DataContext="{Binding PatientSelectorVM}" />
        </ContentControl>
    </Grid>
</UserControl>

enter image description here结果应如下图所示

我需要使用相应的视图模型来显示子窗口。 我不知道该怎么做?

2 个答案:

答案 0 :(得分:1)

您无法直接在ViewModels中访问UI元素(包括窗口)。

只需抽象功能&#34;打开窗口&#34;。最简单的方法是使用interface:

interface IDialogService 
{
    public void OpenWindow(BaseViewModel windowViewModel);
}

//in viewmodel:
void OpenPatientWindow_CommandExecuted()
{
     var patientWindowVM = new PatientWindowViewModel())
     patientWindowVM.Parameter = "This way you can pass parameters";
    _dialogService.OpenWindow(patientWindowVM);
}

到这里获取更多灵感:Handling Dialogs in WPF with MVVM

答案 1 :(得分:0)

将ContentPresenter的Content属性绑定到MainWindow.xaml中MainViewModel PatientVM 属性,并使用为每个子视图/视图模型类型定义一个DataTemplate:

<ContentControl Content="{Binding PatientVM}">
    <ContentControl.Resources>
        <DataTemplate DataType="local:PatientSelectorVM">
            <v:PatientWindow />
        </DataTemplate>
        <DataTemplate DataType="local:ThirdScreenType">
            <v:ThirdScreenView />
        </DataTemplate>
    </ContentControl.Resources>
</ContentControl>

然后,您将PatientVM的{​​{1}}属性设置为MainViewModel对象,以显示PatientWindow视图和PatientSelectorVM对象(或者您的类实际调用的任何对象) )在ContentControl中显示其他视图。

确保ThirdScreenType实现MainViewModel接口并在INotifyPropertyChanged属性的setter中引发PropertyChanged事件:

PatientVM

为了能够将属性设置为PatientSelectorVM对象和其他类型的对象,这些类应该派生自相同的基类或实现相同的接口。