如何从父视图的ViewModel(属性)分配DataContext

时间:2015-10-30 18:57:29

标签: wpf mvvm data-binding

编辑: 这是一个小样本解决方案(VS 2013),显示我的确切问题:nakkvarr.net/TestApp.zip

我有两种观点:

  • 的MainView
  • EmployeeView

我希望我的EmployeeView引用MainViewModel属性“employees”。 我试过这个:

    <DockPanel DataContext="{Binding DataContext.MainViewModel,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type EmployeeLisViewModel}}}">

但我得到的是错误:WPF中不支持EmployeeListViewModel? (EmployeeListViewModel也是我的MainViewModel属性的名称)

事情是: 我的MainView有一些菜单项。一个用于对员工列表进行排序,该列表位于我的UserControl中。我的UserControl ViewModel包含用于排序的命令。

编辑: 我将其更改为vm:EmployeeListViewModel ...现在错误消失了......但现在我似乎无法访问ViewModel:/

<ia:InvokeCommandAction Command="{Binding LoadEmployeesCommand}"

不触发,没有加载员工。当我直接使用ViewModel时,它可以正常工作。

MainWindow.xaml
    <Window x:Class="de.XXX.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:controls="clr-namespace:de.XXX.Views"
            xmlns:vm="clr-namespace:de.XXX.ViewModel"
            Icon="/Images/App.ico"
            Style="{StaticResource MainWindowStyle}"
            Title="MainWindow">
        <DockPanel  DataContext="{Binding MainViewModel, Source={StaticResource Locator}}">
            <Menu DockPanel.Dock="Top">
                ...
            </Menu>
            <controls:EmployeeListView DockPanel.Dock="Bottom" DataContext="{Binding EmployeeListViewModel}" />
        </DockPanel>
    </Window>

EmployeeListView.xaml //not model, copy & paste error x_X
<UserControl x:Class="de.XXX.Views.EmployeeListView"
             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:de.XXX.ViewModel"
             xmlns:ia="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             mc:Ignorable="d" 
             d:DesignHeight="350" d:DesignWidth="350">
    <DockPanel DataContext="{Binding MainViewModel,
    RelativeSource={RelativeSource FindAncestor, 
    AncestorType={x:Type vm:EmployeeListViewModel}}}">

        <ListBox DockPanel.Dock="Bottom" x:Name="EmployeeList" ItemsSource="{Binding EmployeeList}" ScrollViewer.CanContentScroll="False" />

    <ia:Interaction.Triggers>
        <ia:EventTrigger EventName="Loaded">
            <ia:InvokeCommandAction Command="{Binding LoadEmployeesCommand}" />
        </ia:EventTrigger>
    </ia:Interaction.Triggers>
    </DockPanel>
</UserControl>

2 个答案:

答案 0 :(得分:1)

我认为这里可能存在误解的组合!你的UserControl有

x:Class="de.XXX.Views.EmployeeListView"

定义为xaml中的类名。但是,您还说该文件名为EmployeeListView Model .xaml?永远不应将.xaml文件命名为viewmodel。我相信你应该有MainWindow.xaml,EmployeeListView.xaml,MainWindowViewModel.cs和EmployeeListViewModel.cs,是这样吗?

此外,在您的MainWindow.xaml中,您已经设置了EmployeeListView用户控件的datacontext:

 <controls:EmployeeListView DockPanel.Dock="Bottom" DataContext="{Binding EmployeeListViewModel}" />

这对我来说意味着你的类结构是MainViewModel包含EmployeeListViewModel的实例......这是真的吗?

如果以上都是真的,那么UserControl xaml的这部分没有意义:

<DockPanel DataContext="{Binding MainViewModel,
RelativeSource={RelativeSource FindAncestor, 
AncestorType={x:Type vm:EmployeeListViewModel}}}">

EmployeeListViewModel实际上是您的视图而不是 viewmodel ,属性&#34; MainViewModel&#34;在EmployeeListViewModel上不存在,因此绑定永远不会起作用。

如果您尝试在UserControl中引用Window的DataContext,MainViewModel,可能的方法是:

MainWindow.xaml:

<controls:EmployeeListView DockPanel.Dock="Bottom" DataContext="{Binding}" />

这应该将EmployeeListView的DataContext设置为MainViewModel。然后,在EmployeeListView中,您可以执行以下操作:

<UserControl x:Class="de.XXX.Views.EmployeeListView"
             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:de.XXX.ViewModel"
             xmlns:ia="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             mc:Ignorable="d" 
             d:DesignHeight="350" d:DesignWidth="350">
    <DockPanel
        <ListBox DockPanel.Dock="Bottom" x:Name="EmployeeList" ItemsSource="{Binding EmployeeList}" ScrollViewer.CanContentScroll="False" />

    <ia:Interaction.Triggers>
        <ia:EventTrigger EventName="Loaded">
            <ia:InvokeCommandAction Command="{Binding EmployeeListViewModel.LoadEmployeesCommand}" />
        </ia:EventTrigger>
    </ia:Interaction.Triggers>
    </DockPanel>
</UserControl>

我对你的观点和观点模型做了很多假设,我为这个答案做了。我希望这至少有帮助。如果它没有任何意义,请发布您的视图模型:)

答案 1 :(得分:1)

如果您将SubControl修改为以下,这应该可以。

<Grid DataContext="{Binding Path=DataContext.SubVM, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">

我对你想要实现的目标有一个暗示,我猜你已经错过了一些关于绑定的细节,尤其是需要设置的其他底层属性。这部分基于给定的代码工作。但是,有很多方法可以让它变得更好。祝你好运。