将datagrid绑定到一个ViewModel,将列/组合框绑定到另一个ViewModel

时间:2011-07-29 19:03:03

标签: silverlight mvvm

我有一个View Player,datacontext设置为来自ViewModel MainPlayerViewModel的ObservableCollection玩家。

在视图中,我有一个包含TeamId,Name和Position列的数据网格。 我想将TeamId列与组合框绑定到MainTeamViewModel中可用团队的列表,该团队具有集合属性团队,但当然我希望每当我为团队更新团队时都会更新MainPlayerViewModel。

我希望你能在这里关注我.. 这是我的xaml:

<data:DataGridTemplateColumn.CellEditingTemplate>
  <DataTemplate>
   <ComboBox DataContext="{Binding MainTeam, Mode=OneWay, Source={StaticResource Locator}}" 
    Height="23" HorizontalAlignment="Left" 
    Name="cmbTeams" VerticalAlignment="Top" Width="100" ItemsSource="{Binding Teams, 
    Mode=TwoWay}" SelectedValue="{Binding Path=Model.teamid, Mode=TwoWay}"   
    DisplayMemberPath="Model.teamid"/>
  </DataTemplate>
 </data:DataGridTemplateColumn.CellEditingTemplate>

当我编辑单元格时,它显示了可用团队的列表,但是我从列表中选择的selectedvalue没有出现在TeamId列中

如何解决此问题?

亲切的问候,

麦克

更新 尽管我收到了帮助,但我没有让它将一个View绑定到2个不同的View模型。 猜猜提供的解决方案远远超过我的头脑.. 我无法将数据网格的datacontext设置为MainTeam,因为它有一个ItemsSource的玩家和一个选定的绑定到选定的玩家。 无论如何,我决定保留它1 View / 1 ViewModel并在我的PlayerViewModel上创建一个名为teamsVM的公共属性:

    public MainTeamViewModel teamsVM
    {
       get
       {
           return ViewModelLocator.Container.Resolve<MainTeamViewModel>();
       }
    }

现在我可以将Itemsource设置为这个新属性,并在我更换团队时更新我的​​播放器行:

    <DataTemplate>
     <ComboBox 
       Height="23" HorizontalAlignment="Left" 
       Name="cmbTeams" VerticalAlignment="Top" Width="100" 
       ItemsSource="{Binding teamsVM.Teams, 
       Mode=TwoWay}" SelectedValue="{Binding Model.teamid, Mode=TwoWay}"   
       DisplayMemberPath="Model.teamid" SelectedValuePath="Model.teamid"/>
    </DataTemplate>

此致

麦克

2 个答案:

答案 0 :(得分:0)

我发现这个代码有两个问题。

您缺少ComboBox的SelectedValuePath。即使您将所有团队绑定到它,所选项的id也为null,因为缺少SelectedValuePath。

您还有一个DataContext和一个ItemsSource。对于要显示的团队,只使用ItemsSource,并将SelectedValue绑定到玩家的teamId,除非您的视图模型具有“团队”属性和“播放器”属性,在这种情况下可以使用DataContext。 (Id虽然在代码中设置了DataContext)。

所以你最终会得到这样的东西:

ItemsSource="{Binding Teams, Mode=TwoWay}"                  //Bind to all teams.
SelectedValue="{Binding Player, Path=TeamId, Mode=TwoWay}"  //Bind to the teamId of the player.
DisplayMemberPath="TeamName"                                //that's the Name of each team.
SelectedValuePath="TeamId"                                  //that's the Id of the team.

答案 1 :(得分:0)

这里有两个问题:

  • 首先,正如@bleepzer所说,你没有在组合框中指定值/显示路径。
  • 其次,您尝试从数据模板中访问网格外部的数据上下文中的属性(即主视图模型的数据上下文)。在silverlight 4中没有相对源绑定(你将在SL 5或WPF中使用的东西),所以你必须使用元素绑定来存档你想要的东西。

以下是基于您的代码的示例。它不完整,因为它省去了一些所需的DataGrid元素,但它显示了这个概念:

<data:DataGrid x:Name="myDataGrid" 
               DataContext="{Binding MainTeam, Mode=OneWay, Source={StaticResource Locator}}" >
  <!-- additional stuff needed here -->
    <data:DataGridTemplateColumn.CellEditingTemplate>
      <DataTemplate>
        <ComboBox Height="23" HorizontalAlignment="Left" 
                  Name="cmbTeams" VerticalAlignment="Top" Width="100" 
                  ItemsSource="{Binding ElementName=myDataGrid, Path=DataContext.Teams}" 
                  SelectedValuePath="TeamId"
                  DisplayMemberPath="TeamName"
                  SelectedValue="{Binding Path=Model.teamid, Mode=TwoWay}"/>
      </DataTemplate>
    </data:DataGridTemplateColumn.CellEditingTemplate>
  <!-- additional stuff needed here -->
<data:DataGrid>

以下是描述:

  1. 为数据网格添加名称。
  2. 确保数据网格具有正确的数据上下文,方法是在示例中明确设置,或者从父层次结构继承数据网格。
  3. 使用您之前指定的元素名称修改ComboBox的{​​{1}}属性以指向数据网格。由于您现在处于元素而不是数据上下文中,因此必须使用ItemsSource来访问网格数据上下文中的DataContex.Teams属性。 ItemsSource不需要双向绑定,因为视图不会将任何内容写回视图模型。
  4. 指定TeamsSelectedValuePath属性。
  5. 最后,使用双向绑定将组合框的DisplayMemberPath属性绑定到行模型SelectedValue - 现在需要,因为视图应更新模型的值。 重要:组合框的TeamId属性必须在<{strong> SelectedValue之后绑定,以防止组合框出现问题。