views:

212

answers:

1

I have a class like this:

public class Contest {
    List<ContestTeam> Teams { get; set; }
}

public class ContestTeam {
    int TeamId { get; set; }
    int FinalScore { get; set; }
}

And my view model looks like this:

public class ScheduleViewModel {
    int CurrentTeamId { get; }
    List<Contest> Schedule { get; }
}

My Xaml looks something like this:

<ListBox ItemsSource="{Binding Path=Schedule}">
    <ListBox.ItemTemplate>
     <DataTemplate>

      <Grid>
       <Grid.ColumnDefinitions>
        <ColumnDefinition  />
       </Grid.ColumnDefinitions>
       <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
       </Grid.RowDefinitions>

       <StackPanel Grid.Row="0" Orientation="Horizontal">
        <!-- TODO: DataContext is currently hard coded to 425 - this needs to be fixed -->
        <StackPanel Orientation="Horizontal" 
          DataContext="{Binding Path=Teams, Converter={StaticResource CurrentTeam}, ConverterParameter=425}">

         <TextBlock Text="{Binding SomeProperty}" />
        </StackPanel>

        <Button Content="Delete" />
       </StackPanel>

       <ListBox Grid.Row="1" ItemsSource="{Binding Teams}">
        <!-- a list of all the teams -->
       </ListBox>
      </Grid>

     </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Essentially, so I can continue developing I created a value converter (CurrentTeam) and hard-coded the TeamId as the ConverterParameter so I can continue developing the view. But I'm at a bit of an impasse. Is there a way (using Xaml) to bind the DataContext of the StackPanel to the ContestTeam in the Teams collection that matches the value of ScheduleViewModel.TeamId?

My last recourse will be to just use the Loaded event of the StackPanel to set it's DataContext in the code-behind, but I'd like to avoid that. Are there any Xaml Ninjas out there who can help me figure this out?

+1  A: 

There's no way to make queries in XAML bindings. In this case, since you really have two input values (Teams and CurrentTeamId), just use a MultiBinding and a IMultiValueConverter:

public class FindContestByIdConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType,
                          object parameter, CultureInfo culture)
    {
        var teams = (IEnumerable<ContestTeam>)values[0];
        var teamId = (int)values[1];
        return teams.Single(t => t.TeamId == teamId);
    }

    // ConvertBack that throws NotSupportedException
    ...
}

and then XAML:

<StackPanel>
  <StackPanel.DataContext>
    <MultiBinding Converter="{StaticResource FindContestByIdConverter}">
      <Binding Path="Teams"/>
      <Binding Path="CurrentTeamId" />
    </MultiBinding>
  </StackPanel.DataContext>
  ...
</StackPanel>
Pavel Minaev
Silverlight doesn't support multibinding yet - but I found this link:http://www.scottlogic.co.uk/blog/wpf/2009/06/silverlight-multibindings-how-to-attached-mutiple-bindings-to-a-single-property/
Mark J Miller