Universal Windows Platform – Expand Control

Expand Control demonstrates how to create a Expand Panel Control

Step 1

If not already, follow Setup and Start on how to Install and get Started with Visual Studio 2017 or in Windows 10 choose Start, and then from the Start Menu find and select Visual Studio 2017.

vs2017

Step 2

Once Visual Studio Community 2017 has started, from the Menu choose File, then New then Project…

vs2017-file-new-project

Step 3

From New Project choose Visual C# from Installed, Templates then choose Blank App (Universal Windows) and then type in the Name as ExpandControl and select a Location and then select Ok to create the Project
vs2017-new-project-expand-control

Step 4

Then in New Universal Windows Project you need to select the Target Version this should be at least the Windows 10 Fall Creators Update (10.0; Build 16299) and the Minimum Version to be the same.

vs2017-target-platform

The Target Version will control what features your application can use in Windows 10 so by picking the most recent version you’ll be able to take advantage of those features. To make sure you always have the most recent version, in Visual Studio 2017 select Tools Extensions and Updates… then and then see if there are any Updates

Step 5

Once done select from the Menu, Project, then Add New Item…

vs2017-project-add-new-item

Step 6

From the Add New Item window select Visual C#, then XAML from Installed then select Templated Control from the list, then type in the Name as ExpandPanel.cs before selecting Add to add the file to the Project

vs2017-add-new-item-expand-control

Step 7

Once in the Code View for Dial.cs below the end of public ExpandPanel() { … } the following Code should be entered:

private bool _useTransitions = true;
private VisualState _collapsedState;
private Windows.UI.Xaml.Controls.Primitives.ToggleButton _toggleExpander;
private FrameworkElement _contentElement;

public static readonly DependencyProperty HeaderContentProperty =
DependencyProperty.Register("HeaderContent", typeof(object),
typeof(ExpandPanel), null);

public static readonly DependencyProperty MainContentProperty =
DependencyProperty.Register("MainContent", typeof(object),
typeof(ExpandPanel), null);

public static readonly DependencyProperty IsExpandedProperty =
DependencyProperty.Register("IsExpanded", typeof(bool),
typeof(ExpandPanel), new PropertyMetadata(true));

public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.Register("CornerRadius", typeof(CornerRadius),
typeof(ExpandPanel), null);

public object HeaderContent
{
	get { return GetValue(HeaderContentProperty); }
	set { SetValue(HeaderContentProperty, value); }
}

public object MainContent
{
	get { return GetValue(MainContentProperty); }
	set { SetValue(MainContentProperty, value); }
}

public bool IsExpanded
{
	get { return (bool)GetValue(IsExpandedProperty); }
	set { SetValue(IsExpandedProperty, value); }
}

public CornerRadius CornerRadius
{
	get { return (CornerRadius)GetValue(CornerRadiusProperty); }
	set { SetValue(CornerRadiusProperty, value); }
}

private void ChangeVisualState(bool useTransitions)
{
	if (IsExpanded)
	{
		if (_contentElement != null)
		{
			_contentElement.Visibility = Visibility.Visible;
		}
		VisualStateManager.GoToState(this, "Expanded", useTransitions);
	}
	else
	{
		VisualStateManager.GoToState(this, "Collapsed", useTransitions);
		_collapsedState = (VisualState)GetTemplateChild("Collapsed");
		if (_collapsedState == null)
		{
			if (_contentElement != null)
			{
				_contentElement.Visibility = Visibility.Collapsed;
			}
		}
	}
}

protected override void OnApplyTemplate()
{
	base.OnApplyTemplate();
	_toggleExpander = (Windows.UI.Xaml.Controls.Primitives.ToggleButton)
		GetTemplateChild("ExpandCollapseButton");
	if (_toggleExpander != null)
	{
		_toggleExpander.Click += (object sender, RoutedEventArgs e) =>
		{
			IsExpanded = !IsExpanded;
			_toggleExpander.IsChecked = IsExpanded;
			ChangeVisualState(_useTransitions);
		};
	}
	_contentElement = (FrameworkElement)GetTemplateChild("Content");
	if (_contentElement != null)
	{
		_collapsedState = (VisualState)GetTemplateChild("Collapsed");
		if ((_collapsedState != null) && (_collapsedState.Storyboard != null))
		{
			_collapsedState.Storyboard.Completed += (object sender, object e) =>
			{
				_contentElement.Visibility = Visibility.Collapsed;
			};
		}
	}
	ChangeVisualState(false);
}

In the ExpandPanel.cs there are Members to indicate if it should use transitions, VisualState for when the Panel is Collapsed, a ToggleButton to switch between states and a FrameworkElement for content of the Control. There are properties for HeaderContent for anything to put in the header of the Control, MainContent for the main content of the Control and IsExpanded indicates if the Control is collapsed or not and there’s a CornerRadius for styling of the Control. ChangeVisualState is used to switch between the Collapsed and Normal states of the Control and is used by OnApplyTemplate to toggle between the states of the Control by responding to a ToggleButton that can “collapse” the Control.

Step 8

Once done select from the Menu, Build, then Build Solution

vs2017-build-build-solution

Step 9

From Solution Explorer select Generic.xaml

vs2017-generic-expand-control

Step 10

From the Menu choose View and then Designer

vs2017-view-designer

Step 11

The XAML View will be displayed and in this remove the following XAML:

<Border
	Background="{TemplateBinding Background}"
	BorderBrush="{TemplateBinding BorderBrush}"
	BorderThickness="{TemplateBinding BorderThickness}">
</Border>

And replace it with the following XAML:

<Grid>
	<VisualStateManager.VisualStateGroups>
		<VisualStateGroup x:Name="ViewStates">
			<VisualStateGroup.Transitions>
				<VisualTransition GeneratedDuration="0:0:0.5"/>
			</VisualStateGroup.Transitions>
			<VisualState x:Name="Expanded">
				<Storyboard>
					<DoubleAnimation Storyboard.TargetName="ContentScaleTransform"
					Storyboard.TargetProperty="ScaleY" To="1" Duration="0"/>
					<DoubleAnimation Storyboard.TargetName="RotateButtonTransform"
					Storyboard.TargetProperty="Angle" To="180" Duration="0"/>
				</Storyboard>
			</VisualState>
			<VisualState x:Name="Collapsed">
				<Storyboard>
					<DoubleAnimation Storyboard.TargetName="ContentScaleTransform"
					Storyboard.TargetProperty="ScaleY" To="0" Duration="0"/>
					<DoubleAnimation Storyboard.TargetName="RotateButtonTransform"
					Storyboard.TargetProperty="Angle" To="0" Duration="0"/>
				</Storyboard>
			</VisualState>
		</VisualStateGroup>
	</VisualStateManager.VisualStateGroups>
	<Border BorderBrush="{TemplateBinding BorderBrush}"
	BorderThickness="{TemplateBinding BorderThickness}"
	CornerRadius="{TemplateBinding CornerRadius}"
	Background="{TemplateBinding Background}">
		<Grid>
			<Grid.RowDefinitions>
				<RowDefinition Height="Auto"/>
				<RowDefinition Height="*"/>
			</Grid.RowDefinitions>
			<Grid Margin="3">
				<Grid.ColumnDefinitions>
					<ColumnDefinition Width="*"/>
					<ColumnDefinition Width="Auto"/>
				</Grid.ColumnDefinitions>
				<ContentPresenter Grid.Column="0" VerticalAlignment="Center" Content="{TemplateBinding HeaderContent}" FontSize="16"/>
				<ToggleButton Grid.Column="1" RenderTransformOrigin="0.5,0.5" x:Name="ExpandCollapseButton">
					<ToggleButton.Template>
						<ControlTemplate>
							<Grid Margin="5">
								<Ellipse Width="50" Height="50" Fill="{ThemeResource SystemControlHighlightAccentBrush}"/>
								<Path RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Center" VerticalAlignment="Center"
								Data="M2,3L9,10 16,3" Stroke="{ThemeResource SystemControlBackgroundAltHighBrush}" StrokeThickness="4"/>
							</Grid>
						</ControlTemplate>
					</ToggleButton.Template>
					<ToggleButton.RenderTransform>
						<RotateTransform x:Name="RotateButtonTransform"/>
					</ToggleButton.RenderTransform>
				</ToggleButton>
			</Grid>
			<ContentPresenter Grid.Row="1" Margin="5" Content="{TemplateBinding MainContent}" x:Name="Content">
				<ContentPresenter.RenderTransform>
					<ScaleTransform x:Name="ContentScaleTransform"/>
				</ContentPresenter.RenderTransform>
			</ContentPresenter>
		</Grid>
	</Border>
</Grid>

The block of XAML that needs to be removed is a Border that isn’t needed for the ExpandPanel so it is replaced with a Grid which contains the VisualTransition and Storyboard for the animations between states for the Control for Normal and Collapsed plus there are also the VisualState themselves for each of those too. There’s a Grid to create the layout of the control made up of the HeaderContent which is also contains a ToggleButton to switch between the states of the Control and there’s the MainContent displayed when expanded.

Step 12

Once done select from the Menu, Build, then Build Solution

vs2017-build-build-solution

Step 13

In the Solution Explorer select MainPage.xaml

vs2017-mainpage

Step 14

From the Menu choose View and then Designer

vs2017-view-designer

Step 15

The Design View will be displayed along with the XAML View and in this between the Grid and /Grid elements, enter the following XAML:

<local:ExpandPanel Margin="50" HeaderContent="Expander" HorizontalAlignment="Center" VerticalAlignment="Top">
	<local:ExpandPanel.MainContent>
		<StackPanel>
			<Rectangle Width="50" Height="50" Margin="10" Fill="Black"/>
			<Rectangle Width="50" Height="50" Margin="10" Fill="Gray"/>
			<Rectangle Width="50" Height="50" Margin="10" Fill="Red"/>
			<Rectangle Width="50" Height="50" Margin="10" Fill="Orange"/>
			<Rectangle Width="50" Height="50" Margin="10" Fill="Yellow"/>
		</StackPanel>
	</local:ExpandPanel.MainContent>
</local:ExpandPanel>

The block of XAML represents the Expander with the HeaderContent set to some Text and the MainContent is set to a StackPanel containing some Rectangle Controls.

Step 16

That completes the Universal Windows Platform Application so Save the Project then in Visual Studio select the Local Machine to run the Application

vs2017-local-machine

Step 17

After the Application has started running it should then appear with the Expand Panel displayed which can expanded or contracted when the ToggleButton at the top is tapped.

ran-expand-control

Step 18

To Exit the Application select the Close button in the top right of the Application

vs2017-close

Creative Commons License

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s