Marcello Grechi Lins
Marcello Grechi Lins

Reputation: 3410

How to Programatically Tab Switching Using Views?

i am "designing" interfaces for an app written in C# WPF.

To make maintenance and understanding easier i wrapped each tab content in a different XAML file. So in my project, i got a folder called "Views" which have 3 XAML files, representing one tab of the app in each file.

I want to be able to navigate between those tabs, as soon as a button is pressed into a certain tab.

e.g : I am at Tab one called, Configuration. (the other two tabs are hidden). As soon as i hit a "start" button i want my Actual tab to be hidden,and the second tab to be shown in its place.

The problem is, i have a main window that holds the tabs just like this :

<DockPanel LastChildFill="True">
    <StatusBar Name="statusBar" DockPanel.Dock="Bottom" Height="22">
        <StatusBarItem x:Name="messagePanel" Content="Ready" VerticalAlignment="Center" />
        <StatusBarItem Grid.Column="1" Margin="5,2" HorizontalAlignment="Right" >
            <ProgressBar x:Name="progressPanel" IsIndeterminate="False" Width="160" Height="18" Visibility="Collapsed" />
        </StatusBarItem>
    </StatusBar>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="190" />
            <RowDefinition Height="6" />
            <RowDefinition Height="110*" />
        </Grid.RowDefinitions>

        <views:EventsView x:Name="eventsView" Grid.Row="2" Margin="4" />

        <GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" Margin="0" VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext" ShowsPreview="True" ResizeDirection="Rows" />

        <TabControl Margin="4" Name="tabControl1">
            <TabItem Header="Configuration" Name="tabItemConfiguration">
                <views:Configuration />
            </TabItem>

            <TabItem Header="Classification" Name="tabItemClassification" Visibility="Hidden">
                <views:Classifier/>
            </TabItem>                
        </TabControl>

    </Grid>
</DockPanel>

Question: How do i swich from one tab to another one programatically on the "click" event of a button ? Remember that i am at a different XAML file, so i dont have access (at least i dont know how to get access) to the reference of another tab as i would do on the code behind the main window

Thanks in advance, and sorry for that long code pasted

EDIT:

Doing this gave me access to the tabs, but how do i show the content of the tab instead of just the little tab ?

MainWindow.Instance.tabItemClassification.Visibility = Visibility.Visible;
MainWindow.Instance.tabItemConfiguration.Visibility  = Visibility.Visible;

I want to actually show the content of the second tab

Upvotes: 0

Views: 341

Answers (2)

Rachel
Rachel

Reputation: 132548

I would highly recommend looking into the MVVM Design Pattern

With this pattern, you would bind your TabControl.ItemsSource to a collection of objects that represent your tab items, and bind the SelectedItem or SelectedIndex to another data field in the DataContext. Each of theTabItems would be a ViewModel, and get drawn using a different View, and to change the selected item you would set the SelectedValue property.

Here's an example.

Your class that is the DataContext for your MainView would look like this:

public class MainViewModel : INotifyPropertyChanged
{
    // These should be expanded into full properties with get/set methods
    // and the set method should raise the PropertyChanged event
    public ObservableCollection<ITabViewModel> TabViewModels { get; set; }
    public ITabViewModel SelectedTabIndex { get; set; }
    public ICommand ChangeTabCommand { get; set; }

    public MainViewModel()
    {
        TabViewModels = new ObservableCollection<ITabViewModel>();
        TabViewModels.Add(new ConfigurationTabViewModel());
        TabViewModels.Add(new ClassificationTabViewModel());

        SelectedTabIndex = 0;

        ChangeTabCommand = new RelayCommand<int>(ChangeTabIndex);
    }

    void ChangeTabIndex(int tabIndex)
    {
        if (tabIndex >= 0 && tabIndex < TabViewModels.Count)
            SelectedTabIndex = tabIndex;
    }

    // Also implement INotifyPropertyChanged
}

In this case, your main XAML view would look like this:

<TabControl ItemsSource="{Binding TabViewModels}"
            SelectedIndex="{Binding SelectedTabIndex}">

    <TabControl.Resources>
        <Style TargetType="{x:Type TabItem}">
            <Setter Property="Header" Value="{Binding Header}" />
        </Style>

        <DataTemplate DataType="{x:Type viewModels:ConfigurationTabViewModel}">
            <views:Configuration />
        </DataTemplate>

        <DataTemplate DataType="{x:Type viewModels:ClassificationTabViewModel}">
            <views:Classification />
        </DataTemplate>

    </TabControl.Resources>

</TabControl>

If you're interested, I have a simple MVVM example posted on my blog which includes more information about INotifyPropertyChange and RelayCommand, and the article about Navigation with MVVM contains a very similar example to what I posted here although it swaps out the Content in a ContentControl instead of the SelectedItem in a TabControl.

Upvotes: 1

Marcello Grechi Lins
Marcello Grechi Lins

Reputation: 3410

This solved my problems.

MainWindow.Instance.tabItemClassification.Visibility = Visibility.Visible;
        MainWindow.Instance.tabItemConfiguration.Visibility = Visibility.Hidden;

        // Changes the view to the classification tab
        MainWindow.Instance.tabController.SelectedIndex = 1;

Have a good day.

Upvotes: 0

Related Questions