Specialized containers are a variant of content controls but unlike content controls which can hold simple content type such as string or UIElement object, the specialized containers has larger impact and they affect the outlook of the larger portion of content visible on the screen. In this article, some important and extremely handy WPF specialized containers have been explained. The first control that we will discuss is the ScrollViewer control that provides a scrollable space in which other elements can be placed. The ScrollViewer control directly inherits the ContentControl class, thus allowing only single element to be placed inside it. The other three important Specialized containers that inherit from HeaderedContentControl (which inherits from the ContentControl) are TabItem, Expander and GroupBox. Difference between the HeaderedContentControl and the parent ContentControl class is that the former control can hold two elements, one in the header space and the other in the content space, whereas the latter can only hold one element. This article is for the readers having basic understanding of the WPF syntax and those who idea of the application structure of WPF. If you are totally new to WPF, I would suggest you to first read this article explaining basics of WPF. You can then comeback and continue with this tutorial. If you have prior understanding of WPF, you are already good to go. The ScrollViewer GroupBox TabItem Expander The ScrollViewer Situation often arises where you need to add large amounts of data on limited amounts of space. In such scenarios, using WPF ScrollViewer controls is the best solution. The idea of the ScrollViewer control is that it actually wraps all the content that you want to place in a scrollable window. Though, the ScrollViewer can hold only single element like all other content controls, using a layout container can help placing multiple controls in the scrollable window. The following example demonstrates actually how a ScrollViewer control can be used to scroll through multiple controls in a Grid layout. Have a look at the first example of this article: Example1 Code: <Window x:Class="WPFTutorial.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="180" Width="400" MinWidth="150"> <ScrollViewer> <Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <TextBox Margin="5" Grid.Row="0" Grid.Column="0"> Text Box1</TextBox> <Button Margin="5" Grid.Row="0" Grid.Column="1">Button1</Button> <TextBox Margin="5" Grid.Row="1" Grid.Column="0">Text Box2</TextBox> <Button Margin="5" Grid.Row="1" Grid.Column="1">Button2</Button> <TextBox Margin="5" Grid.Row="2" Grid.Column="0">Text Box2</TextBox> <Button Margin="5" Grid.Row="2" Grid.Column="1">Button2</Button> <TextBox Margin="5" Grid.Row="3" Grid.Column="0">Text Box3</TextBox> <Button Margin="5" Grid.Row="3" Grid.Column="1">Button3</Button> <TextBox Margin="5" Grid.Row="4" Grid.Column="0">Text Box4</TextBox> <Button Margin="5" Grid.Row="4" Grid.Column="1">Button4</Button> <TextBox Margin="5" Grid.Row="5" Grid.Column="0">Text Box5</TextBox> <Button Margin="5" Grid.Row="5" Grid.Column="1">Button5</Button> </Grid> </ScrollViewer> </Window> Pay close attention to the code in Example1, here a ScrollViewer control has been added inside the top level Window control. Inside the ScrollViewer control a Layout control Grid has been added, we discussed earlier that ScrollViewer control can only nest one child element in it. To add more than one element, an intermediate Layout container can be used which is Grid in this case. The Grid Layout contains 7 rows and two columns. In the first column of all the rows TextBox controls have been added and in the second columns of all the rows, button controls have been. However, the height of the top level Window control is only 180 device independent points. All the rows of the Grid cannot fit in the column, but since the Grid has been wrapped inside a ScrollViewer control, therefore a vertical scroll bar will appear that can be used to scroll and see the contents inside the output window. The output of the code in Example1 is as follows: Output1 It can be seen from the output that a scroll bar has appeared on the right side of the window. If screen is resized to the extent that all the controls can fit into it, the scroll bar will automatically disappeared. It will reappear again if the window is shrinking back to smaller size so that all the contents can fit into it. In Example1, by default a vertical scroll bar has appeared. If you also want a horizontal scroll bar on your window, the HorizontalScrollBarVisibility property of the ScrollViewer control can be set to True or Auto. The HeaderedContentControl In this section, three of the most commonly used HeaderedContentControls i.e. GroupBox, TabItem and the Expander controls have been explained. GroupBox The HeaderedContentControl consists of a header and content. The simplest of all the HeaderedContentControls is the GroupBox control. The GroupBox control consists of a box with a header that contains a title. The second Example of this tutorial demonstrates the usage of GroupBox control. Have a look at the code in Example2. Example2 Code: <Window x:Class="WPFTutorial.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="200" Width="100" MinWidth="150"> <GroupBox VerticalAlignment="Top" Margin="5" Padding="5" Header="Choose Color"> <StackPanel> <RadioButton> Blue</RadioButton> <RadioButton> Red</RadioButton> <RadioButton>Black</RadioButton> <RadioButton>Green</RadioButton> <Button> Save Settings</Button> </StackPanel> </GroupBox> </Window> Here in Example2, a GroupBox control has been added. The Header property of the GroupBox control is used to set the title of the GroupBox control. In this case, the title has been set to “Choose Color”. Inside the GroupBox control, a StackPanel has been added which contains four RadioButton controls and a simple Button control. Since the StackPanel is inside the GroupBox control. A box with round edges will appear around all the four RadioButton controls and a simple Button control. The output of the code in Example2 would look like this: Output2 In the output, a thin box is visible around all the button control; the title of the GroupBox is “Choose Color” which is also visible. TabItem Another extremely important HeaderedContentControl is the TabItem control which actually represents a tab or a page in TabControl. The most important property of the TabItem class is the IsSelected property which basically tells whether the current tab is the one that is being displayed on the TabControl. To see the actual working of the TabItem, have a look at the third example of this tutorial. Example3 Code: <Window x:Class="WPFTutorial.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="200" Width="100" MinWidth="200"> <TabControl> <TabItem Header="Choose Size"> <StackPanel> <RadioButton> Small</RadioButton> <RadioButton> Medium</RadioButton> <RadioButton>Large</RadioButton> <RadioButton>Extra Large</RadioButton> <Button> Save Settings</Button> </StackPanel> </TabItem> <TabItem Header="Choose Color" IsSelected="True"> <StackPanel> <RadioButton>Blue</RadioButton> <RadioButton>Red</RadioButton> <RadioButton>Black</RadioButton> <RadioButton>Green</RadioButton> <Button>Save Settings</Button> </StackPanel> </TabItem> </TabControl> </Window> In Example3, A TabControl element has been added in the top level Window element. Inside the TabControl element, two HeaderedContentControl TabItem controls have been added. The first TabItem control has a title “Choose Size”. Inside this TabItem a StackPanel has been added which contains four radio controls having different content representing the sizes. At the end a simple button control with content “Save Settings” have been added in the StackPanel. Next another TabItem control with Header property set to “Choose Color” has been added to the TabControl. The second TabItem is slightly different from the first one. The IsSelected property of the second TabItem is set to True, which means that this TabItem will be displayed on the TabControl by default when application runs. The second TabItem also contains a StackPanel with some RadioButtons and a simple Button control. The output of the code in Example3 would look like this: Output3 It can be seen clearly in the above figure that by default, the second tab with header “Choose Color” is displayed on the TabControl. This is due to the fact that its IsSelected property has been set to True. If no TabItem has this property set to true then by default the first TabItem will be displayed on the TabControl when the application runs. A very interesting thing about the Header of the TabItem controls is that since Header portion can hold one child. Therefore, a StackPanel of any other Layout can be placed inside the header of a TabItem. Inside the StackPanel, as many items as you like can be placed. This is done by accessing the Header portion of TabItem by calling TabItem.Header attached property of the TabItem whose header is to be accessed. The next example of this tutorial demonstrates this concept. Have a look at the fourth example of this article: Example4 Code: <Window x:Class="WPFTutorial.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="200" Width="100" MinWidth="200"> <TabControl> <TabItem Header="Choose Size" IsSelected="True"> <StackPanel> <RadioButton> Small</RadioButton> <RadioButton> Medium</RadioButton> <RadioButton>Large</RadioButton> <RadioButton>Extra Large</RadioButton> <Button> Save Settings</Button> </StackPanel> </TabItem> <TabItem IsSelected="True"> <TabItem.Header> <StackPanel> <TextBox>Text Box1</TextBox> <Button>Button1</Button> </StackPanel> </TabItem.Header> <StackPanel> <RadioButton>Blue</RadioButton> <RadioButton>Red</RadioButton> <RadioButton>Black</RadioButton> <RadioButton>Green</RadioButton> <Button>Save Settings</Button> </StackPanel> </TabItem> </TabControl> </Window> The above code is similar to the one in Example3, but here in the second TabItem of the TabControl. The attached TabItem.Header property has been used to access the Header portion of the TabItem. Inside the Header, a StackPanel has been defined which contains A TextBox and a Button. Now instead of the string content, a TextBox and a Button will appear in the Header portion of the second TabItem. The output of the code in Example4 is as follows: Output4 It can be seen from the output that second TabItem’s header contains a text box and a button as mentioned in the code. Expander The last control in the category of the HeaderedContentControls is the the Expander control which is probably one of the most fascinating controls in the entire WPF controls library. The basic idea of the Expander control is to wrap large amounts of data in a small portion. The user will have to click a small arrow button that will expand the underlying information. This technique is similar to webpages, where a slider window opens upon clicking a small link or arrow button. Let us see the Expander control in action with the help of an example. Have a look at the 5th example of this tutorial. Example5 Code: <Window x:Class="WPFTutorial.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="400" Width="100" MinWidth="200"> <StackPanel> <Expander Header="Sizes"> <StackPanel> <RadioButton> Small</RadioButton> <RadioButton> Medium</RadioButton> <RadioButton>Large</RadioButton> <RadioButton>Extra Large</RadioButton> <Button> Save Settings</Button> </StackPanel> </Expander> <Expander Header="Colors"> <StackPanel> <RadioButton>Blue</RadioButton> <RadioButton>Red</RadioButton> <RadioButton>Black</RadioButton> <RadioButton>Green</RadioButton> <Button>Save Settings</Button> </StackPanel> </Expander> </StackPanel> </Window> In the above code, there is a StackPanel Layout inside the top level Window element. Inside this StackPanel, there are two Expander controls. Each Expander control contains one internal stack panel and inside that stack panel few RadioButton controls and one simple Button has been placed. The first Expander control’s Header property has been set to Sizes and the second Expander’s header property has been set to Colors. In the output of the above code, two Expander controls will be added in the form of a stack. The top element would be the Sizes element. The bottom element will be the Colors element. To the left of both these elements, a small arrow button would appear which would point downwards. This means that if this button is clicked, the control will expand downwards and display the content that it wraps. Once a control is expanded, the Button arrow would point upwards, which means that control is already expanded and clicking the button would collapse it upwards. The output of the code in Example5 is as follows: Output5: Here, the Sizes Expander has been expanded and the Colors Expander has not yet been expanded. Clicking the button left to the Colors will expand the Colors element as well. Example6 Code: <Window x:Class="WPFTutorial.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="400" Width="100" MinWidth="200"> <StackPanel> <Expander ExpandDirection="Right" Header="Sizes"> <StackPanel> <RadioButton> Small</RadioButton> <RadioButton> Medium</RadioButton> <RadioButton>Large</RadioButton> <RadioButton>Extra Large</RadioButton> <Button> Save Settings</Button> </StackPanel> </Expander> <Expander ExpandDirection="Left" Header="Colors"> <StackPanel> <RadioButton>Blue</RadioButton> <RadioButton>Red</RadioButton> <RadioButton>Black</RadioButton> <RadioButton>Green</RadioButton> <Button>Save Settings</Button> </StackPanel> </Expander> </StackPanel> </Window> The above example is similar to the one in the last example, however here in this case; the two Expanders have an additional attribute ExpandDirection. The ExpandDirection property or the attribute of the first Expander control has been set to the Right, which means that the content of this control would expand to right. Similarly, the ExpandDirection attribute of the second Expander control has been set to Left which will expand the content to the left. The output of the code in above example is as follows: Output6 In the output, A button appears on the top with text Sizes below it. The arrow in the button would point to right since its direction is set to right, and if this arrow is clicked, the content expands on the right as shown in the output. For the second, Expander control, the arrow direction of the button would be towards left since it has ExpandDirection property set to left.