I'm trying to create a databound Tabcontrol, where each TabItem contains a Datagrid, also databound.
My data structure is something like this:
public class Exercise
{
public Guid ExerciseID { get; protected set; }
public string ExerciseName { get; set; }
public List<Set> Sets { get; set; }
}
public class Set
{
public Guid SetID { get; protected set; }
public decimal Weight { get; set; }
public decimal Reps { get; set; }
public bool MaxEffort { get; set; }
}
I'm trying to bind a List<Exercise>
to a TabControl, and the List<Set>
for each Exercise to the DataGrid within each Tab, displaying the "Weight" and "Reps" properties in two columns. My current XAML code is below, with the relevant section labelled.
<Window x:Class="MyWorkouts.WorkoutViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WorkoutViewer" Height="424" Width="708"
x:Name="WorkoutDisplay">
<Grid DataContext="{DynamicResource WorkoutToDisplay}">
<Calendar SelectedDate="{Binding WorkoutDate}" Height="180" HorizontalAlignment="Left" Margin="8,12,0,0" Name="calendar1" VerticalAlignment="Top" Width="230" />
<StackPanel Height="94" HorizontalAlignment="Left" Margin="12,182,0,0" Name="spProperties" VerticalAlignment="Top" Width="238">
<StackPanel Height="30" Name="spProgram" Width="232" Orientation="Horizontal">
<Label Content="Workout Program:" Height="25" Name="lblProgram" Width="104" />
<TextBox Text="{Binding WorkoutProgram}" Height="25" Name="tbProgram" Width="120" />
</StackPanel>
<StackPanel Height="30" Name="spType" Width="232" Orientation="Horizontal">
<Label Content="Workout Type:" Height="25" Name="lblWorkoutType" Width="104" />
<TextBox Text="{Binding WorkoutType}" Height="25" Name="tbWorkoutType" Width="120" />
</StackPanel>
<StackPanel Height="30" Name="spVenue" Width="232" Orientation="Horizontal">
<Label Content="Workout Venue:" Height="25" Name="lblVenue" Width="104" />
<TextBox Text="{Binding WorkoutVenue}" Height="25" Name="tbVenue" Width="120" />
</StackPanel>
</StackPanel>
<TabControl Height="365" HorizontalAlignment="Left" Margin="260,10,0,0" Name="TCWorkoutView" VerticalAlignment="Top" Width="425">
<TabItem Header="Workout View" Name="TIView">
<StackPanel Height="335" HorizontalAlignment="Left" Name="spExercises" VerticalAlignment="Top" Width="410" Grid.ColumnSpan="2">
<ItemsControl ItemsSource="{Binding Exercises}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander Header="{Binding ExerciseName}" BorderThickness="1" BorderBrush="DarkBlue">
<ItemsControl ItemsSource="{Binding Sets}" DisplayMemberPath="WeightForReps" BorderThickness="1" BorderBrush="Gray"/>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</TabItem>
<!--The below section is the one in question-->
<TabItem Header="Edit Workout">
<TabControl ItemsSource="{Binding Path=Exercises}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding Path=Sets}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Weight" Binding="{Binding Path=Weight}"/>
<DataGridTextColumn Header="Reps" Binding="{Binding Path=Reps}"/>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</TabControl>
</TabItem>
</TabControl>
</Grid>
I've got as far as having the ExerciseName property correctly displayed in each Tab (with the correct number of tabs generated, but there's no datagrid at all, instead the Tab just says MyWorkouts.Exercise (MyWorkouts is the namespace).
For a bit of background, this is meant to be the "Edit" screen for a workout logging program, and I've got the display view working correctly with a stackpanel of expanders - I need whatever solution I have to be editable, and have the changes made in the datagrid reflected in the appropriate class objects - I hope to work this out myself, but if this approach won't work, please let me know!
EDIT: My full XAML code is now listed above
Needed to set the TabControl.ContentTemplate
rather than the ItemsControl.ItemTemplate
. Once I switched that, I could use the DisplayMemberPath property, and everything else worked!
The XAML code I needed was:
<TabControl ItemsSource="{Binding Path=Exercises}" DisplayMemberPath="ExerciseName">
<TabControl.ContentTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding Path=Sets}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Weight" Binding="{Binding Path=Weight}"/>
<DataGridTextColumn Header="Reps" Binding="{Binding Path=Reps}"/>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>