C# 如何将多视图模型添加到主窗口中的用户控件

C# 如何将多视图模型添加到主窗口中的用户控件,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,这是我第一次尝试实现MVVM模型,因此我提前表示歉意。我有一个主窗口,它有自己的ViewModel。然后,主窗口有三个用户控件,根据在导航菜单中选择的内容,可以加载这些控件。但是,数据上下文不会更改为正确的视图模型 main window.xaml <Window.DataContext> <VM:MainVM></VM:MainVM> </Window.DataContext> <Window.Resources>

这是我第一次尝试实现MVVM模型,因此我提前表示歉意。我有一个主窗口,它有自己的ViewModel。然后,主窗口有三个用户控件,根据在导航菜单中选择的内容,可以加载这些控件。但是,数据上下文不会更改为正确的视图模型

main window.xaml

<Window.DataContext>
    <VM:MainVM></VM:MainVM>
</Window.DataContext> 

<Window.Resources>
    <DataTemplate x:Key="View1Template" DataType="{x:Type VM:CustomerVM}">
        <View:Customers  DataContext="{Binding VM:CustomerVM}" />
    </DataTemplate>

    <DataTemplate x:Key="View2Template" DataType="{x:Type VM:SuppliersVM}">
        <View:Suppliers DataContext="{Binding VM:Suppliers}"/>
    </DataTemplate>
</Window.Resources>

<ContentControl  Margin="0,135,0,10" Grid.Column="1">
    <ContentControl.Style>
        <Style TargetType="{x:Type ContentControl}">
            <Setter Property="ContentTemplate"  Value="{StaticResource View1Template}" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding SwitchView}" Value="0">
                    <Setter Property="ContentTemplate" Value="{StaticResource View1Template}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding SwitchView}" Value="1">
                    <Setter Property="ContentTemplate" Value="{StaticResource View2Template}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ContentControl.Style>
</ContentControl>
<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <i:InvokeCommandAction Command="{Binding LoadCustomersCommand}" />
    </i:EventTrigger>
</i:Interaction.Triggers>
<Grid>
    <TextBox Tag="Search Customers" x:Name="searchTextBox" Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" HorizontalAlignment="Left" Height="40" Margin="10,9,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="340" Padding="5,6,0,0" FontSize="16"/>
    <Label Content="{Binding Path=SearchText}" Margin="430,0,436,263" />
    <ListView ItemsSource="{Binding Customers}" x:Name="customerListBox" Margin="10,57,10,10"  AlternationCount="2"   >
        <ListView.View>
            <GridView>
                <GridViewColumn Header="ID" Width="Auto" DisplayMemberBinding="{Binding id}" />
                <GridViewColumn Header="NAME" Width="Auto" DisplayMemberBinding="{Binding name}"  />
                <GridViewColumn Header="ADDRESS" Width="Auto" DisplayMemberBinding="{Binding address1}" />
                <GridViewColumn Header="ADDRESS 2" Width="150" DisplayMemberBinding="{Binding address2}" />
                <GridViewColumn Header="TOWN" Width="150" DisplayMemberBinding="{Binding town}" />
                <GridViewColumn Header="COUNTY" Width="150" DisplayMemberBinding="{Binding county}" />
                <GridViewColumn Header="POSTCODE" Width="150" DisplayMemberBinding="{Binding postcode}" />
                <GridViewColumn Header="PHONE" Width="150" DisplayMemberBinding="{Binding phone}" />
                <GridViewColumn Header="EMAIL" Width="150" DisplayMemberBinding="{Binding email}" />
            </GridView>
        </ListView.View>   
    </ListView>
</Grid>
CustomerVM.cs

private string _searchText;
private readonly ObservableCollection<Customer> _customers = new ObservableCollection<Customer>();

public string Title = "Customers";

public string SearchText
{
    get { return _searchText; }
    set
    {
        _searchText = value;
        RaisePropertyChangedEvent("SearchText");
    }
}

public IEnumerable<Customer> Customers
{
    get { return _customers; }
}

public ICommand LoadCustomersCommand
{
    get { return new DelegateCommand(LoadCustomers); }
}

public void LoadCustomers()
{
    Customer cus = new Customer { id = 1, name = "sam" };
    _customers.Add(cus);

}
public ICommand NavigationClick
{
    get { return new DelegateCommand(Navigate); }
}

public void Navigate()
{        
    SwitchView = 1;
}

我认为这里发生了几件事。我们将从一开始我最清楚的一个开始

DataContext
是一个对象——通常是viewmodel类的实例。
DataTemplate
用于显示viewmodel类的实例。其
DataContext
由其包含的控件继承。这可能是您想要的:

<Window.Resources>
    <DataTemplate DataType="{x:Type VM:CustomerVM}">
        <View:Customers />
    </DataTemplate>

    <DataTemplate DataType="{x:Type VM:SuppliersVM}">
        <View:Suppliers />
    </DataTemplate>
</Window.Resources>
在XAML中,内容控制被大大简化。无论您在
SelectedChild
中输入什么内容,都将显示在内容控件中。它如何知道要使用哪个模板

简单:我们从上面的数据模板中去掉了
x:Key
属性,但保留了
DataType
属性。这使它们成为所谓的“隐式数据模板”:无论它们在范围内的何处,都将被需要显示这些类型对象的任何
ContentControl
自动使用。在此
窗口中的任何位置
,如果您告诉XAML“这是一个
CustomerVM
;向用户显示”,XAML将使用上述两个数据模板中的第一个来显示它

<ContentControl 
    Content="{Binding SelectedChild}"
    Margin="0,135,0,10" 
    Grid.Column="1"
    />


您可以去掉
SwitchView
属性。您所做的工作当然是有效的(正如您所发现的,在XAML中做一些工作并不总是容易的),但这种方法更简单、更传统

请说明如何在XAML中使用这些数据模板。您不需要在模板内的视图上显式设置DataContext;它将继承datatemplate的DataContext。
DataContext=“{Binding VM:CustomerVM}”
是什么意思?你想给它一个类型吗?谢谢你的更新。ContentControl的
内容是从哪里获得的?我已经更新了有关如何加载视图的问题。
CustomerVM
是Customer-User-Control视图的视图模型。我将更详细地更新这个问题。这方面的学习曲线非常陡峭。查看我的更新:您所做的一切都会起作用,但
MainVM
如何与孩子们互动呢?它甚至找不到它们。我的更新展示了一个简单的设计,解决了这个问题。我现在已经实现了这个梦想,帮助我更多地理解了MVVM,再次感谢。如果你有任何博客或在线教程,我会感兴趣,因为你的方法和解释是明确的。
public MainVM()
{
    Customer = new CustomerVM();
    Supplier = new SupplierVM();
}

public CustomerVM Customer {
    get { return _customerVM; }
    private set { _customerVM = value; }
}
public SupplierVM Supplier {
    get { return _supplierVM; }
    private set { _supplierVM = value; }
}

public INotifyPropertyChanged _selectedChild;
public INotifyPropertyChanged SelectedChild {
    get { return _selectedChild; }
    set {
        if (value != _selectedChild) {
            _selectedChild = value;
            //  I don't know how you raise PropertyChanged; if it doesn't look 
            //  like this, let me know. 
            OnPropertyChanged();
        }
    }
}

public void Navigate()
{        
    SelectedChild = Customer;
}
<ContentControl 
    Content="{Binding SelectedChild}"
    Margin="0,135,0,10" 
    Grid.Column="1"
    />