Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / UWP

[Uwp] Make a Resizable Splitview

5.00/5 (3 votes)
27 Sep 2018CPOL4 min read 11.9K  
A very simple Resizable SplitView

Introduction

It has been a long time since my last tip, a tip that luckily was turned obsolete by the nice addition of the GridSplitter in the always helpful Windows Community Toolkit

This time, I decided to redeem myself by providing an insanely simple and smart way to implement draggable behavior from scratch,.

More specifically, I will implement a way to resize a SplitView Pane, something that I think is probably the most practical use of a Draggable function and GridSplitter cannot do.

This will be a comparably long article if you consider the simplicity of the implementation, this is because I put on an introductory/educational character to it, so if you are the kind of guy that feeds on sample code, just go ahead and check the GitHub repo.

Background

You will need:

  • Visual Studio 2017 with UWP dev kit installed on a recent SDK version
  • Knowing how to write a few lines of code 

Implementation

Setting Up

First things first, we create a new UWP Project and set the solution name as “DragSplitView”.

Wait for it to load and then we go and open the MainPage.xaml.

Now we will begin to carve out the skeleton of our Design, we will name the main Grid of the page as MasterGrid and add the following RowDefinitions to it:   

XML
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions> 

On the First Row, we assign a ToggleButton and we call it “OpenButton”, we set IsChecked="True"

IsChecked="True", we assign an icon inside it: <SymbolIcon Symbol="More" />

On the Second Row, we will assign a new SplitView, we call that “CoreSplitView”, we set DisplayMode="Inline".

For more information about Grid and Placement Definitions, check the Appendix below.

The End Result should look like this:

XML
<Page
    x:Class="DragSplitView.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:DragSplitView"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    mc:Ignorable="d">
   <Grid Name="MasterGrid">
           <Grid.RowDefinitions>
               <RowDefinition Height="auto"/>
               <RowDefinition Height="1*"/>
           </Grid.RowDefinitions>
           <ToggleButton Name="OpenButton" IsChecked="True">
               <SymbolIcon Symbol="More" />
           </ToggleButton>

           <SplitView Name="CoreSplitView"
            Grid.Row="1"
            DisplayMode="Inline">
           </SplitView>
   </Grid>
</Page>

Basic Binding

It is time to implement the basic Interactivity of our App, to do this, we will use the Binding system, if you are new to Binding and want to learn more, check this out.

We will control the Open State of our SplitView Pane, in other words, the checked state of our ToggleButton will reflect the state of our SplitView, this is easily done through Binding.

We will add the following inside our SplitView Properties:

C#
IsPaneOpen="{Binding IsChecked,ElementName=OpenButton}"
OpenPaneLength="400"

You can now run the program and see how the button controls the state, notice how element ElementName, refers to our ToggleButton, and that IsChecked refers to the involved property inside that ToggleButton.

Finishing Up

We will finalize the UI Layout so we can move to the last Phase.

We go ahead and expose the <SplitView.Pane> and we add a Grid called "PaneGrid" and set on Background="Gold", this Grid on its own accord will host the following new control:

XML
<Slider Name="MasterSlider"
                        MinWidth="480"
                        VerticalAlignment="Stretch"
                        Maximum="480"
                        Minimum="20"
                        Opacity="0"
                        Value="150" />

This is a Slider control and it serves a core purpose, we will dive deeper later.

Below this Slider, we add this:

XML
<StackPanel
Name="PaneStackPanel"
Margin="0,0,20,0"
Background="MediumAquamarine">
<TextBlock TextWrapping="Wrap" Text="this is a custom draggable implementation that is pretty cool,
                               for more stuff check me out at www.codeproject.com/Members/Georgemns" />
</StackPanel>

Under </SplitView.Pane>, we will add a Grid called "ContentGrid" and set on Background="LightSteelBlue".

Last, but not the least important action is to change the:

C#
OpenPaneLength="400"

to:

C#
OpenPaneLength="{Binding Value, ElementName=MasterSlider, Mode=OneWay}"

As you might have guessed, Value is the current Progress of our Slider, and thanks to this statement, it will be "connected" to OpenPaneLength, in a OneWay mode. 

So that’s all you gotta do, if you have been following so far, here is how the document should look:

XML
  <Page  x:Class="DragSplitView.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:DragSplitView"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    mc:Ignorable="d">
   <Grid Name="MasterGrid">
           <Grid.RowDefinitions>
               <RowDefinition Height="auto"/>
               <RowDefinition Height="1*"/>
           </Grid.RowDefinitions>
           <ToggleButton Name="OpenButton" IsChecked="True">
               <SymbolIcon Symbol="More" />
           </ToggleButton>
           <SplitView Name="CoreSplitView"
            Grid.Row="1"
            DisplayMode="Inline"
            IsPaneOpen="{Binding IsChecked,ElementName=OpenButton}"
            OpenPaneLength="{Binding Value, ElementName=MasterSlider, Mode=OneWay}" >
               <SplitView.Pane>
                   <Grid Name="PaneGrid" Background="Gold">
                       <Slider Name="MasterSlider"
                        MinWidth="480"
                        VerticalAlignment="Stretch"
                       Maximum="480"
                        Minimum="20"
                        Opacity="0"
                        Value="150" />
                     <StackPanel Name="PaneStackPanel" 
                     Margin="0,0,20,0" Background="MediumAquamarine">
                       <TextBlock TextWrapping="Wrap" Text="this is a custom draggable implementation
                       that is pretty cool, for more stuff check me out
                       at www.codeproject.com/Members/Georgemns" />
                       </StackPanel>
                   </Grid>
               </SplitView.Pane>
               <Grid Name="ContentGrid" Background="LightSteelBlue">
               </Grid>
           </SplitView>
   </Grid>
</Page>

Dissection

As I said, Slider is the heart of this system, Slider’s Current Progress (Value) directly reflects to the current Pane Width of the Pane, through the Binding expression showcased above and much like how implemented the open-close function with that button.

Now into more specifics:

  • We assign MinWidth="480", Maximum="480" and Minimum="20" on that Slider because the slider would otherwise change width and “compress” thus losing the 1-1 pixel to progress parity we have, 480 is just an arbitrary number that we choose to be as the Maximum potential Width that our pane can Expand to, likewise Minimum is the Minimum Width of the Pane, it is good to note that you should seek for a Maximum number that is below 500, as this is the default minimum window size.
  • We also set Value="150", as the starting point when our app starts up, you might choose to expand this implementation by saving the current value and then load it back up when your app starts again.
  • VerticalAlignment =”Stretch”, this what allows the Slider to cover up the entire Vertical Space, in other words, the slider will no longer act like a thin strip of color, but an entire area that can potentially respond to any user input inside the Pane.
  • Opacity="0", this is a smart way of making something invisible, notice how we don’t use the actual Visibility property, this is because turning down the opacity will still allow us to interact with the bar even if you don’t actually see it.

The StackPanel that is directly under our slider, acts like a cover for our Slider. Notice how it has Margin="0,0,20,0", this translates to a 20px distance from the right wall, which allows the Slider Area to be exposed as a golden strip that is used to drag the Pane, again the 20px is arbitrary but it has to match the Minimum of the Slider.

Image 1

History

  • 27th September, 2018: Published

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)