I am creating a WPF Tabbed Interface utility program using MVVM Light. While free-standing dialog boxes live in their own .xaml
files, my understanding was that to create tabbed interface panels, the code for those should reside in a DataTemplate
within my MainWindow.xaml
.
Everything was working fine until I needed to customize the appearance of the DataGrid
. What I wanted was to call an event handler when a grid was created that would iterate through the columns and do some custom things for certain columns. So I added an Initialized
event handler to the DataGrid
. It only gets called when the first tab with a DataGrid
is created... or when I close all the tabs and open a new first DataGrid
tab. A little more investigation and I discover that DataContextChanged
happens whenever I create a subsequent grid or click between tabs.
I'm thinking that I've committed a design flaw, that while there is a separate view-model for each grid, there is only a single, common grid resource, but am unsure how to correct it.
My Question: How do I go about creating a completely separate grid for each tab?
DataTemplate
from MainWindow.xaml:
<Window...>
<Window.Resources>
<DataTemplate DataType="{x:Type vm:GridViewModel}">
<Grid>
<DataGrid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,32" RowHeight="{Binding RowHeight}" SelectionUnit="Cell"
IsReadOnly="True" LoadingRow="DataGrid_LoadingRow" ItemsSource="{Binding RecordSet}" AutoGenerateColumns="false"
Initialized="DataGrid_Initialized" DataContextChanged="DataGrid_DataContextChanged" >
</DataGrid>
</Grid>
</DataTemplate>
</Window.Resources>
</Window>
TabControl
from within Grid
from MainWindow.xml
<TabControl x:Name="DocumentArea" ItemsSource="{Binding Workspaces}" SelectedIndex="{Binding SelectedIndex}" HorizontalAlignment="Stretch" Margin="0,35,0,35" VerticalAlignment="Stretch">
<TabControl.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Header}" />
<Button Command="{Binding CloseCommand}" Content="X" Margin="4,0,0,0" FontFamily="Courier New" Width="17" Height="17" VerticalContentAlignment="Center" />
</WrapPanel>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
Example of a method in MainViewModel.cs that creates a Grid:
private void ShowAccountsGrid()
{
GridViewModel viewModel = new GridViewModel { Header = "QuickBooks Chart of Accounts" };
Workspaces.Add(viewModel);
SelectedIndex = Workspaces.IndexOf(viewModel);
viewModel.RecordSet = _quickBooksHelper.AccountList;
}
Relevant code from GridViewModel.cs:
public class GridViewModel : WorkspaceViewModel
{
private readonly IDataService _dataService;
public RelayCommand DoDeleteRow { get; set; }
public RelayCommand DoShowRowDetail { get; set; }
[PreferredConstructor]
public GridViewModel(IDataService dataService) :base()
{
InitBoundFields();
SetupRelayCommands();
_dataService = dataService;
_dataService.GetData(
(item, error) =>
{
if (error != null)
{
// Report error here
return;
}
});
}