개발하는 두더지

[C/C++/C#/UWP] UWP Customized SplitView 코드 - 1 본문

C,C++

[C/C++/C#/UWP] UWP Customized SplitView 코드 - 1

덜지 2016. 10. 21. 16:06

SplitView란?


윈도우 10은 UWP에서 많은 새로운 기능들을 제공합니다. 새로운 컨트롤 중 하나가 SplitView 입니다. 

이 컨트롤은 페이지 이동을 더 쉽게 할 수 있도록 도와줍니다. 

오늘 만들어볼 예제는 아래 그림과 같습니다.



<Desktop>

<Mobile>




소스코드 전체


MainPage.xaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<Page
    x:Class="SplitViewContorl1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SplitViewContorl1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    
    xmlns:triggers="using:WindowsStateTriggers"
    >
 
    <Page.Resources>
        <ResourceDictionary>
            <SolidColorBrush x:Key="NavButtonPressedBackgroundBrush" Color="White" Opacity="0.3"/>
            <SolidColorBrush x:Key="NavButtonCheckedBackgroundBrush" Color="White" Opacity="0.2"/>
            <SolidColorBrush x:Key="NavButtonHoverBackgroundBrush" Color="White" Opacity="0.1"/>
 
            <Style x:Key="NavRadioButtonStyle" TargetType="RadioButton">
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="Padding" Value="3"/>
                <Setter Property="HorizontalAlignment" Value="Stretch"/>
                <Setter Property="VerticalAlignment" Value="Center"/>
                <Setter Property="HorizontalContentAlignment" Value="Left"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="RadioButton">
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                        <VisualState x:Name="Normal"/>
                                        <VisualState x:Name="PointerOver">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundGrid">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource NavButtonHoverBackgroundBrush}"/>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Pressed">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundGrid">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource NavButtonPressedBackgroundBrush}"/>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Disabled"/>
                                    </VisualStateGroup>
                                    <VisualStateGroup x:Name="CheckStates">
                                        <VisualState x:Name="Checked">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundGrid">
                                                    <DiscreteObjectKeyFrame  KeyTime="0" Value="{StaticResource NavButtonCheckedBackgroundBrush}"/>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Unchecked"/>
                                        <VisualState x:Name="Indeterminate"/>
                                    </VisualStateGroup>
                                    <VisualStateGroup x:Name="FocusStates">
                                        <VisualState x:Name="Focused"/>
                                        <VisualState x:Name="UnFocused"/>
                                        <VisualState x:Name="PointerFocused"/>
                                    </VisualStateGroup>
                                </VisualStateManager.VisualStateGroups>
                                <Grid Name="BackgroundGrid" Background="Transparent" VerticalAlignment="Stretch">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="48"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <TextBlock FontSize="34" Height="38" Text="{TemplateBinding Tag}" FontFamily="Segoe MDL2 Assets" Margin="5,8,5,5" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                                    <ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" Grid.Column="1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" TextWrapping="Wrap" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                </Grid>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ResourceDictionary>
    </Page.Resources>
 
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="phone">
                    <VisualState.StateTriggers>
                        <triggers:DeviceFamilyStateTrigger DeviceFamily="Mobile"/>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="BackRadioButton.Visibility" Value="Collapsed"/>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <SplitView x:Name="SplitView" OpenPaneLength="240" CompactPaneLength="48" DisplayMode="CompactOverlay" IsPaneOpen="False" PaneBackground="DarkGray">
            <SplitView.Pane>
                <StackPanel x:Name="SplitViewPanePanel">
                    <RadioButton x:Name="BackRadioButton" Click="BackRadioButton_Click" Background="Gray" Content="Back" GroupName="Back" Tag="" Style="{StaticResource NavRadioButtonStyle}"/>
                    <RadioButton x:Name="HamburgerRadioButton" Click="HamburgerRadioButton_Click" Content="Menu" GroupName="Hamburger" Tag="" Style="{StaticResource NavRadioButtonStyle}"/>
                    <RadioButton x:Name="HomeRadioButton" Click="HomeRadioButton_Click" Content="Home" GroupName="Navigation" Tag="" Style="{StaticResource NavRadioButtonStyle}"/>
                    <RadioButton x:Name="SettingsRadioButton" Click="SettingsRadioButton_Click" Content="Settings" GroupName="Navigation" Tag="" Style="{StaticResource NavRadioButtonStyle}"/>
                </StackPanel>
            </SplitView.Pane>
            <SplitView.Content>
                <Frame Name="MyFrame" Background="Bisque">
                </Frame>
            </SplitView.Content>
        </SplitView>
    </Grid>
</Page>
 
 
 
    
cs


MainPage.xaml.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
 
// 빈 페이지 항목 템플릿은 http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 에 문서화되어 있습니다.
 
namespace SplitViewContorl1
{
    /// <summary>
    /// 자체적으로 사용하거나 프레임 내에서 탐색할 수 있는 빈 페이지입니다.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            MyFrame.Navigate(typeof(Page1));
        }
 
        private void BackRadioButton_Click(object sender, RoutedEventArgs e)
        {
            if (MyFrame.CanGoBack)
            {
                MyFrame.GoBack();
            }
        }
 
        private void HamburgerRadioButton_Click(object sender, RoutedEventArgs e)
        {
            if(!this.SplitView.IsPaneOpen)
            {
                this.SplitView.IsPaneOpen = true;
            }
            else
            {
                this.SplitView.IsPaneOpen = false;
            }
        }
 
        private void HomeRadioButton_Click(object sender, RoutedEventArgs e)
        {
            MyFrame.Navigate(typeof(Page1));
        }
 
        private void SettingsRadioButton_Click(object sender, RoutedEventArgs e)
        {
            MyFrame.Navigate(typeof(Page2));
        }
    }
}
 
cs


Page1.xaml

1
2
3
<Grid Background="LightBlue">
        <TextBlock FontSize="36" Text="HomePage" Margin="12,17,0,17" />
</Grid>
cs


Page2.xaml

1
2
3
<Grid Background="SteelBlue">
    <TextBlock FontSize="36" Text="Settings page" Margin="12,17,0,17"/>
</Grid>
cs


그리고 라디오버튼은 Tag="" 라는 속성을 주고있습니다. 
아래의 문자표에서 복사해서 Tag 값에 넣어야 합니다.
시작-> Windows  보조프로그램 -> 문자표 -> 글꼴선택 ( Segoe MDL2 Assets )


1
<TextBlock FontSize="34" Height="38" Text="{TemplateBinding Tag}" FontFamily="Segoe MDL2 Assets" Margin="5,8,5,5" VerticalAlignment="Center" HorizontalAlignment="Center"/>
cs
FontFamily 값에 위의 문자표의 글꼴을 설정하기 때문에 그림 기호들을 사용 할 수 있습니다.




UI 문제점

가끔씩 디자인이 PC와 모바일에 전부 맞지 않을때가 있습니다.
 예를들어 모바일의 경우 하드웨어 Back버튼이 있는데 위의 예제에서는 화면안에 Back 버튼이 있습니다.
이럴 경우에 디바이스 종류에 따라 앱의 UI를 커스터마이징 해야합니다. 
모바일 전용 xaml 페이지를 만들수있지만 이번 예제에서는 Nuget 패키지의 상태트리거를 다뤄보겠습니다.





 NuGet 이란?


프로젝트에 포함할 오픈 소스 라이브러리를 쉽게 설치 및 업데이트 시켜주고 관리하는 Visual Studio 확장 툴입니다.





디바이스 타입에 따라 트리거 주기

MainPage.xaml 의 <Page> 태그 속성

1
2
3
4
5
6
7
8
9
10
11
<Page
    x:Class="SplitViewContorl1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SplitViewContorl1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    
    xmlns:triggers="using:WindowsStateTriggers"
    >
cs
xmlsns:triggers="using:WindowsStateTriggers"
위에서 설치한 NuGet 패키지를 UI 페이지에 세팅합니다.


MainPage.xaml 의 <Grid> 태그 내부

1
2
3
4
5
6
7
8
9
10
11
12
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="phone">
                    <VisualState.StateTriggers>
                        <triggers:DeviceFamilyStateTrigger DeviceFamily="Mobile"/>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="BackRadioButton.Visibility" Value="Collapsed"/>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
cs


부분으로 가져왔지만 위의 전체코드안에 포함되어 있습니다.

상태 트리거를 이용함으로써 디바이스 타입에 따라 다른 UI 를 제공할 수 있습니다.



Comments