昨天想在 uwp 上实现,在 SplitView 控件的左侧,通过手指滑动打开 SplitView 的 Pane 面板,
而不仅仅是通过 “汉堡按钮” 点击打开。
在 stackoverflow 看到一个帖子, 有讨论一个方案,然后看了一下里面的一个 github 工程,实现了
SwipeableSplitView(工程连接), 不过下载代码分析了一下,代码量太大,通过继承 SplitView 控件,添加很多 xaml 和
C# 代码,有点复杂了。于是想了一个简单的方式,直接控制 SplitView 中 Template 的 CompositeTransform 和
VisualTransition 属性就可以了,几十行 C# 代码就能搞定。
1、运行效果 (VS2015 创建的 win10 UWP 工程)
1)在 phone上:

2)在 win10 pc 上:

2、分析 SplitView 控件的模板(只用来分析,并不使用)
1)在空白页面中,添加一个 SplitView,在文档大纲中,右键单击 SplitView 控件,选择编辑副本:

2)在生成的代码中,可以看到,当前 SplitView 控件的组成部分:
这里重点使用 PaneRoot 中的 PaneTransform 属性,和 视觉状态属性中的 VisualTransition From="Closed" To="OpenOverlayLeft" 属性。

VS 所有生成的 SplitView 的 Template 代码:

1 <ControlTemplate x:Key="SplitViewControlTemplate1" TargetType="SplitView">
2 <Grid Background="{TemplateBinding Background}">
3 <VisualStateManager.VisualStateGroups>
4 <VisualStateGroup x:Name="DisplayModeStates">
5 <VisualStateGroup.Transitions>
6 <VisualTransition From="Closed" To="OpenOverlayLeft">
7 <Storyboard>
8 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
9 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
10 </ObjectAnimationUsingKeyFrames>
11 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
12 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
13 </ObjectAnimationUsingKeyFrames>
14 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneTransform" Storyboard.TargetProperty="TranslateX">
15 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.NegativeOpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
16 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/>
17 </DoubleAnimationUsingKeyFrames>
18 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX">
19 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
20 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/>
21 </DoubleAnimationUsingKeyFrames>
22 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility">
23 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
24 </ObjectAnimationUsingKeyFrames>
25 </Storyboard>
26 </VisualTransition>
27 <VisualTransition From="Closed" To="OpenOverlayRight">
28 <Storyboard>
29 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
30 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
31 </ObjectAnimationUsingKeyFrames>
32 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment">
33 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/>
34 </ObjectAnimationUsingKeyFrames>
35 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment">
36 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/>
37 </ObjectAnimationUsingKeyFrames>
38 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
39 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
40 </ObjectAnimationUsingKeyFrames>
41 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneTransform" Storyboard.TargetProperty="TranslateX">
42 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
43 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/>
44 </DoubleAnimationUsingKeyFrames>
45 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX">
46 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.NegativeOpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
47 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/>
48 </DoubleAnimationUsingKeyFrames>
49 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility">
50 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
51 </ObjectAnimationUsingKeyFrames>
52 </Storyboard>
53 </VisualTransition>
54 <VisualTransition From="ClosedCompactLeft" To="OpenCompactOverlayLeft">
55 <Storyboard>
56 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width">
57 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
58 </ObjectAnimationUsingKeyFrames>
59 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.Column)">
60 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
61 </ObjectAnimationUsingKeyFrames>
62 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
63 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
64 </ObjectAnimationUsingKeyFrames>
65 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
66 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
67 </ObjectAnimationUsingKeyFrames>
68 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
69 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
70 </ObjectAnimationUsingKeyFrames>
71 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX">
72 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.NegativeOpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
73 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/>
74 </DoubleAnimationUsingKeyFrames>
75 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility">
76 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
77 </ObjectAnimationUsingKeyFrames>
78 </Storyboard>
79 </VisualTransition>
80 <VisualTransition From="ClosedCompactRight" To="OpenCompactOverlayRight">
81 <Storyboard>
82 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width">
83 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="*"/>
84 </ObjectAnimationUsingKeyFrames>
85 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition2" Storyboard.TargetProperty="Width">
86 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
87 </ObjectAnimationUsingKeyFrames>
88 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
89 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
90 </ObjectAnimationUsingKeyFrames>
91 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
92 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
93 </ObjectAnimationUsingKeyFrames>
94 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment">
95 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/>
96 </ObjectAnimationUsingKeyFrames>
97 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment">
98 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/>
99 </ObjectAnimationUsingKeyFrames>
100 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
101 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
102 </ObjectAnimationUsingKeyFrames>
103 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX">
104 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.OpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
105 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/>
106 </DoubleAnimationUsingKeyFrames>
107 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility">
108 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
109 </ObjectAnimationUsingKeyFrames>
110 </Storyboard>
111 </VisualTransition>
112 <VisualTransition From="OpenOverlayLeft" To="Closed">
113 <Storyboard>
114 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
115 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
116 </ObjectAnimationUsingKeyFrames>
117 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
118 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
119 </ObjectAnimationUsingKeyFrames>
120 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneTransform" Storyboard.TargetProperty="TranslateX">
121 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.NegativeOpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
122 </DoubleAnimationUsingKeyFrames>
123 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX">
124 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
125 </DoubleAnimationUsingKeyFrames>
126 </Storyboard>
127 </VisualTransition>
128 <VisualTransition From="OpenOverlayRight" To="Closed">
129 <Storyboard>
130 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
131 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
132 </ObjectAnimationUsingKeyFrames>
133 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment">
134 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/>
135 </ObjectAnimationUsingKeyFrames>
136 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment">
137 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/>
138 </ObjectAnimationUsingKeyFrames>
139 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
140 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
141 </ObjectAnimationUsingKeyFrames>
142 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneTransform" Storyboard.TargetProperty="TranslateX">
143 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
144 </DoubleAnimationUsingKeyFrames>
145 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX">
146 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.NegativeOpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
147 </DoubleAnimationUsingKeyFrames>
148 </Storyboard>
149 </VisualTransition>
150 <VisualTransition From="OpenCompactOverlayLeft" To="ClosedCompactLeft">
151 <Storyboard>
152 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width">
153 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
154 </ObjectAnimationUsingKeyFrames>
155 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.Column)">
156 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
157 </ObjectAnimationUsingKeyFrames>
158 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
159 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
160 </ObjectAnimationUsingKeyFrames>
161 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
162 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
163 </ObjectAnimationUsingKeyFrames>
164 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
165 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
166 </ObjectAnimationUsingKeyFrames>
167 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX">
168 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
169 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.NegativeOpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
170 </DoubleAnimationUsingKeyFrames>
171 </Storyboard>
172 </VisualTransition>
173 <VisualTransition From="OpenCompactOverlayRight" To="ClosedCompactRight">
174 <Storyboard>
175 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width">
176 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="*"/>
177 </ObjectAnimationUsingKeyFrames>
178 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition2" Storyboard.TargetProperty="Width">
179 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
180 </ObjectAnimationUsingKeyFrames>
181 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
182 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
183 </ObjectAnimationUsingKeyFrames>
184 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
185 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
186 </ObjectAnimationUsingKeyFrames>
187 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment">
188 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/>
189 </ObjectAnimationUsingKeyFrames>
190 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment">
191 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/>
192 </ObjectAnimationUsingKeyFrames>
193 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
194 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
195 </ObjectAnimationUsingKeyFrames>
196 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX">
197 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
198 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.OpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
199 </DoubleAnimationUsingKeyFrames>
200 </Storyboard>
201 </VisualTransition>
202 </VisualStateGroup.Transitions>
203 <VisualState x:Name="Closed"/>
204 <VisualState x:Name="ClosedCompactLeft">
205 <Storyboard>
206 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width">
207 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
208 </ObjectAnimationUsingKeyFrames>
209 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.Column)">
210 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
211 </ObjectAnimationUsingKeyFrames>
212 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
213 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
214 </ObjectAnimationUsingKeyFrames>
215 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
216 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
217 </ObjectAnimationUsingKeyFrames>
218 <DoubleAnimation Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX" To="{Binding TemplateSettings.NegativeOpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}" Duration="0:0:0"/>
219 </Storyboard>
220 </VisualState>
221 <VisualState x:Name="ClosedCompactRight">
222 <Storyboard>
223 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width">
224 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="*"/>
225 </ObjectAnimationUsingKeyFrames>
226 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition2" Storyboard.TargetProperty="Width">
227 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
228 </ObjectAnimationUsingKeyFrames>
229 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
230 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
231 </ObjectAnimationUsingKeyFrames>
232 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
233 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
234 </ObjectAnimationUsingKeyFrames>
235 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
236 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="2"/>
237 </ObjectAnimationUsingKeyFrames>
238 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment">
239 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/>
240 </ObjectAnimationUsingKeyFrames>
241 <DoubleAnimation Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX" To="{Binding TemplateSettings.OpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}" Duration="0:0:0"/>
242 </Storyboard>
243 </VisualState>
244 <VisualState x:Name="OpenOverlayLeft">
245 <Storyboard>
246 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
247 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
248 </ObjectAnimationUsingKeyFrames>
249 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
250 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
251 </ObjectAnimationUsingKeyFrames>
252 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility">
253 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
254 </ObjectAnimationUsingKeyFrames>
255 </Storyboard>
256 </VisualState>
257 <VisualState x:Name="OpenOverlayRight">
258 <Storyboard>
259 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
260 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
261 </ObjectAnimationUsingKeyFrames>
262 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment">
263 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/>
264 </ObjectAnimationUsingKeyFrames>
265 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
266 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
267 </ObjectAnimationUsingKeyFrames>
268 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment">
269 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/>
270 </ObjectAnimationUsingKeyFrames>
271 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility">
272 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
273 </ObjectAnimationUsingKeyFrames>
274 </Storyboard>
275 </VisualState>
276 <VisualState x:Name="OpenInlineLeft">
277 <Storyboard>
278 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.Column)">
279 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
280 </ObjectAnimationUsingKeyFrames>
281 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
282 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
283 </ObjectAnimationUsingKeyFrames>
284 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
285 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
286 </ObjectAnimationUsingKeyFrames>
287 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
288 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
289 </ObjectAnimationUsingKeyFrames>
290 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
291 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
292 </ObjectAnimationUsingKeyFrames>
293 </Storyboard>
294 </VisualState>
295 <VisualState x:Name="OpenInlineRight">
296 <Storyboard>
297 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width">
298 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="*"/>
299 </ObjectAnimationUsingKeyFrames>
300 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition2" Storyboard.TargetProperty="Width">
301 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.OpenPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
302 </ObjectAnimationUsingKeyFrames>
303 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
304 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
305 </ObjectAnimationUsingKeyFrames>
306 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
307 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
308 </ObjectAnimationUsingKeyFrames>
309 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="(Grid.Column)">
310 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
311 </ObjectAnimationUsingKeyFrames>
312 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
313 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
314 </ObjectAnimationUsingKeyFrames>
315 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment">
316 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/>
317 </ObjectAnimationUsingKeyFrames>
318 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
319 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
320 </ObjectAnimationUsingKeyFrames>
321 </Storyboard>
322 </VisualState>
323 <VisualState x:Name="OpenCompactOverlayLeft">
324 <Storyboard>
325 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width">
326 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
327 </ObjectAnimationUsingKeyFrames>
328 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.Column)">
329 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
330 </ObjectAnimationUsingKeyFrames>
331 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
332 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
333 </ObjectAnimationUsingKeyFrames>
334 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
335 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
336 </ObjectAnimationUsingKeyFrames>
337 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
338 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
339 </ObjectAnimationUsingKeyFrames>
340 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility">
341 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
342 </ObjectAnimationUsingKeyFrames>
343 </Storyboard>
344 </VisualState>
345 <VisualState x:Name="OpenCompactOverlayRight">
346 <Storyboard>
347 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width">
348 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="*"/>
349 </ObjectAnimationUsingKeyFrames>
350 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition2" Storyboard.TargetProperty="Width">
351 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
352 </ObjectAnimationUsingKeyFrames>
353 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)">
354 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/>
355 </ObjectAnimationUsingKeyFrames>
356 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
357 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
358 </ObjectAnimationUsingKeyFrames>
359 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment">
360 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/>
361 </ObjectAnimationUsingKeyFrames>
362 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment">
363 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/>
364 </ObjectAnimationUsingKeyFrames>
365 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
366 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
367 </ObjectAnimationUsingKeyFrames>
368 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility">
369 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
370 </ObjectAnimationUsingKeyFrames>
371 </Storyboard>
372 </VisualState>
373 </VisualStateGroup>
374 </VisualStateManager.VisualStateGroups>
375
376 <Grid.ColumnDefinitions>
377 <ColumnDefinition x:Name="ColumnDefinition1" Width="{Binding TemplateSettings.OpenPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
378 <ColumnDefinition x:Name="ColumnDefinition2" Width="*"/>
379 </Grid.ColumnDefinitions>
380
381 <!-- Content Area -->
382 <Grid x:Name="ContentRoot" Grid.ColumnSpan="2">
383 <Border Child="{TemplateBinding Content}"/>
384 <Rectangle x:Name="LightDismissLayer" Fill="Transparent" Visibility="Collapsed"/>
385 </Grid>
386
387 <!-- Pane Content Area-->
388 <Grid
389 x:Name="PaneRoot"
390 Grid.ColumnSpan="2"
391 HorizontalAlignment="Left"
392 Visibility="Collapsed"
393 Background="{TemplateBinding PaneBackground}"
394 Width="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}">
395 <Grid.Clip>
396 <RectangleGeometry x:Name="PaneClipRectangle">
397 <RectangleGeometry.Transform>
398 <CompositeTransform x:Name="PaneClipRectangleTransform"/>
399 </RectangleGeometry.Transform>
400 </RectangleGeometry>
401 </Grid.Clip>
402 <Grid.RenderTransform>
403 <CompositeTransform x:Name="PaneTransform"/>
404 </Grid.RenderTransform>
405 <Border Child="{TemplateBinding Pane}"/>
406 <Rectangle
407 x:Name="HCPaneBorder"
408 x:DeferLoadStrategy="Lazy"
409 Visibility="Collapsed"
410 Fill="{ThemeResource SystemControlForegroundTransparentBrush}"
411 Width="1"
412 HorizontalAlignment="Right"/>
413 </Grid>
414 </Grid>
415 </ControlTemplate>
3、在 xaml 页面中,添加一个 Border 控件,显示在窗口的最左侧,检测用户的滑动手势
<!--屏幕左侧手势检测区域, 在实际代码中可以把 Opacity 设置为 0 -->
<Border Grid.RowSpan="2"
ManipulationMode="TranslateX"
ManipulationCompleted="Border_ManipulationCompleted"
ManipulationDelta="Border_ManipulationDelta"
Width="36" Opacity=".5" Background="Green" HorizontalAlignment="Left"/>
通过注册 Manipulation 事件,可以检测底层触摸事件。这个 Border 即为上面 gif 图片中,绿色的部分。
MainPage.xaml 页面中,全部的 xaml :

<Page
x:Class="SwipeableSplitView.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SwipeableSplitView"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" RequestedTheme="Light">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<SplitView x:Name="MySplitView"
DisplayMode="CompactInline"
IsPaneOpen="True"
IsTabStop="False" PaneBackground="#88440000" Loaded="MySplitView_Loaded" CompactPaneLength="88" OpenPaneLength="280" >
<SplitView.Pane>
<ListView Margin="0,60,0,0">
<ListView.Resources>
<Style TargetType="StackPanel">
<Setter Property="Orientation" Value="Horizontal"/>
<Setter Property="Margin" Value="20,20"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="50,0,0,0"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="22"/>
</Style>
<Style TargetType="FontIcon">
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="30"/>
</Style>
</ListView.Resources>
<StackPanel>
<FontIcon Glyph=""/>
<TextBlock Text="页面 1 "/>
</StackPanel>
<StackPanel>
<FontIcon Glyph="" />
<TextBlock Text="页面 2 "/>
</StackPanel>
<StackPanel>
<FontIcon Glyph=""/>
<TextBlock Text="页面 3 "/>
</StackPanel>
</ListView>
</SplitView.Pane>
<Grid>
<!--<Frame/>-->
<TextBlock Text="当窗口宽度最小时,通过鼠标或者手指,从窗口最左侧向右滑动,则打开 SplitView.Pane " Width="250" FontSize="30" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<!--屏幕左侧手势检测区域, 在实际代码中可以把 Opacity 设置为 0 -->
<Border Grid.RowSpan="2"
ManipulationMode="TranslateX"
ManipulationCompleted="Border_ManipulationCompleted"
ManipulationDelta="Border_ManipulationDelta"
Width="36" Opacity=".5" Background="Green" HorizontalAlignment="Left"/>
<!--显示 Debug 数据-->
<Border HorizontalAlignment="Right" Margin="20" Background="Gray" VerticalAlignment="Top">
<TextBlock x:Name="txtDebug" Text="debug" FontSize="30" Foreground="GreenYellow" Margin="10"/>
</Border>
</Grid>
</SplitView>
<!--汉堡按钮-->
<CheckBox IsChecked="{Binding IsPaneOpen,ElementName=MySplitView, Mode=TwoWay}" IsThreeState="False" Height="40" Width="40" VerticalAlignment="Top" HorizontalAlignment="Left" Style="{StaticResource CheckBoxStyle1}">
<FontIcon Glyph="" Foreground="White" FontSize="25" />
</CheckBox>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="visualState">
<VisualState x:Name="wide">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1024" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="MySplitView.DisplayMode" Value="CompactInline" />
<Setter Target="MySplitView.IsPaneOpen" Value="True" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="meddium">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="548" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="MySplitView.DisplayMode" Value="CompactInline" />
<Setter Target="MySplitView.IsPaneOpen" Value="False" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="narrow">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="MySplitView.DisplayMode" Value="Overlay" />
<Setter Target="MySplitView.IsPaneOpen" Value="False" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>
4、在 MainPage.xaml.cs 页面中
1)分析:当 SplitView.IsPaneOpen 设置为 true 时, Pane 的 CompositeTransform 的 TranslateX 的数值变化
在 SplitView 的 Loaded 事件中,把数值打印出来:
// Debug 数据输出,左侧面板 TranslateX 的变化
private void MySplitView_Loaded(object sender, RoutedEventArgs e)
{
#if DEBUG
Grid grid = Utility.FindVisualChild<Grid>(MySplitView);
Binding bind = new Binding();
bind.Path = new PropertyPath("TranslateX");
bind.Source = (grid.FindName("PaneRoot") as Grid).RenderTransform as CompositeTransform;
// 显示到 TextBlock 上
txtDebug.SetBinding(TextBlock.TextProperty, bind);
txtDebug.RegisterPropertyChangedCallback(TextBlock.TextProperty, (dependencyObject, dependencyProperty) =>
{
// 注册 TextBlock.TextProperty 属性回调事件,显示到输出窗口
Debug.WriteLine("txtDebug.Text ; " + txtDebug.Text);
});
#endif
}
在窄窗口模式下,点击 汉堡按钮,查看输出窗口,数值从 280 (SplitView.OpenPaneLength)变为 0:
txtDebug.Text : -280 txtDebug.Text : -279.996 txtDebug.Text : -220.397 txtDebug.Text : -160.79 txtDebug.Text : -101.138 txtDebug.Text : -65.0658 txtDebug.Text : -51.9964 txtDebug.Text : -38.9144 txtDebug.Text : -25.5251 txtDebug.Text : -20.8821 txtDebug.Text : -16.2444 txtDebug.Text : -11.6015 txtDebug.Text : -8.4631 txtDebug.Text : -6.61891 txtDebug.Text : -4.77503 txtDebug.Text : -2.93104 txtDebug.Text : -2.2662 txtDebug.Text : -1.57674 txtDebug.Text : -0.157382 txtDebug.Text : 0
结合 VisualState 中 <VisualTransition From="Closed" To="OpenOverlayLeft"> 节点,
在 0秒到 0:0:0.35 秒时,PaneRoot 由 “隐藏”变为“显示”,并且它的 TranslateX 由 OpenPaneLength
变为 0 :

<VisualTransition From="Closed" To="OpenOverlayLeft">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneTransform" Storyboard.TargetProperty="TranslateX">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.NegativeOpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
2) 添加 C# 中的逻辑,加了注释
#region 从屏幕左侧边缘滑动屏幕时,打开 SplitView 菜单
// SplitView 控件模板中,Pane部分的 Grid
Grid PaneRoot;
// 引用 SplitView 控件中, 保存从 Pane “关闭” 到“打开”的 VisualTransition
// 也就是 <VisualTransition From="Closed" To="OpenOverlayLeft"> 这个
VisualTransition from_ClosedToOpenOverlayLeft_Transition;
private void Border_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
e.Handled = true;
// 仅当 SplitView 处于 Overlay 模式时(窗口宽度最小时)
if (MySplitView.DisplayMode == SplitViewDisplayMode.Overlay)
{
if (PaneRoot == null)
{
// 找到 SplitView 控件中,模板的父容器
Grid grid = Utility.FindVisualChild<Grid>(MySplitView);
PaneRoot = grid.FindName("PaneRoot") as Grid;
if (from_ClosedToOpenOverlayLeft_Transition == null)
{
// 获取 SplitView 模板中“视觉状态集合”
IList<VisualStateGroup> stateGroup = VisualStateManager.GetVisualStateGroups(grid);
// 获取 VisualTransition 对象的集合。
IList<VisualTransition> transitions = stateGroup[0].Transitions;
// 找到 SplitView.IsPaneOpen 设置为 true 时,播放的 transition
from_ClosedToOpenOverlayLeft_Transition = transitions?.Where(train => train.From == "Closed" && train.To == "OpenOverlayLeft").First();
// 遍历所有 transitions,打印到输出窗口
foreach (var tran in transitions)
{
Debug.WriteLine("From : " + tran.From + " To : " + tran.To);
}
}
}
// 默认为 Collapsed,所以先显示它
PaneRoot.Visibility = Visibility.Visible;
// 当在 Border 上向右滑动,并且滑动的总距离需要小于 Panel 的默认宽度。否则会脱离左侧窗口,继续向右拖动
if (e.Cumulative.Translation.X >= 0 && e.Cumulative.Translation.X < MySplitView.OpenPaneLength)
{
CompositeTransform ct = PaneRoot.RenderTransform as CompositeTransform;
ct.TranslateX = (e.Cumulative.Translation.X - MySplitView.OpenPaneLength);
}
}
}
private void Border_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
e.Handled = true;
// 仅当 SplitView 处于 Overlay 模式时(窗口宽度最小时)
if (MySplitView.DisplayMode == SplitViewDisplayMode.Overlay && PaneRoot != null)
{
// 因为当 IsPaneOpen 为 true 时,会通过 VisualStateManager 把 PaneRoot.Visibility 设置为
// Visibility.Visible,所以这里把它改为 Visibility.Collapsed,以回到初始状态
PaneRoot.Visibility = Visibility.Collapsed;
// 恢复初始状态
CompositeTransform ct = PaneRoot.RenderTransform as CompositeTransform;
// 如果大于 MySplitView.OpenPaneLength 宽度的 1/2 ,则显示,否则隐藏
if ((MySplitView.OpenPaneLength + ct.TranslateX) > MySplitView.OpenPaneLength / 2)
{
MySplitView.IsPaneOpen = true;
// 因为上面设置 IsPaneOpen = true 会再次播放向右滑动的动画,所以这里使用 SkipToFill()
// 方法,直接跳到动画结束状态
from_ClosedToOpenOverlayLeft_Transition?.Storyboard?.SkipToFill();
}
ct.TranslateX = 0;
}
}
#endregion
MainPage.xaml.cs 页面中,全部的 C# :

using System;
using System.Collections.Generic;
using System.Diagnostics;
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;
namespace SwipeableSplitView
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
// Debug 数据输出,左侧面板 TranslateX 的变化
private void MySplitView_Loaded(object sender, RoutedEventArgs e)
{
#if DEBUG
Grid grid = Utility.FindVisualChild<Grid>(MySplitView);
Binding bind = new Binding();
bind.Path = new PropertyPath("TranslateX");
bind.Source = (grid.FindName("PaneRoot") as Grid).RenderTransform as CompositeTransform;
// 显示到 TextBlock 上
txtDebug.SetBinding(TextBlock.TextProperty, bind);
txtDebug.RegisterPropertyChangedCallback(TextBlock.TextProperty, (dependencyObject, dependencyProperty) =>
{
// 注册 TextBlock.TextProperty 属性回调事件,显示到输出窗口
Debug.WriteLine("txtDebug.Text : " + txtDebug.Text);
});
#endif
}
#region 从屏幕左侧边缘滑动屏幕时,打开 SplitView 菜单
// SplitView 控件模板中,Pane部分的 Grid
Grid PaneRoot;
// 引用 SplitView 控件中, 保存从 Pane “关闭” 到“打开”的 VisualTransition
// 也就是 <VisualTransition From="Closed" To="OpenOverlayLeft"> 这个
VisualTransition from_ClosedToOpenOverlayLeft_Transition;
private void Border_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
e.Handled = true;
// 仅当 SplitView 处于 Overlay 模式时(窗口宽度最小时)
if (MySplitView.DisplayMode == SplitViewDisplayMode.Overlay)
{
if (PaneRoot == null)
{
// 找到 SplitView 控件中,模板的父容器
Grid grid = Utility.FindVisualChild<Grid>(MySplitView);
PaneRoot = grid.FindName("PaneRoot") as Grid;
if (from_ClosedToOpenOverlayLeft_Transition == null)
{
// 获取 SplitView 模板中“视觉状态集合”
IList<VisualStateGroup> stateGroup = VisualStateManager.GetVisualStateGroups(grid);
// 获取 VisualTransition 对象的集合。
IList<VisualTransition> transitions = stateGroup[0].Transitions;
// 找到 SplitView.IsPaneOpen 设置为 true 时,播放的 transition
from_ClosedToOpenOverlayLeft_Transition = transitions?.Where(train => train.From == "Closed" && train.To == "OpenOverlayLeft").First();
// 遍历所有 transitions,打印到输出窗口
foreach (var tran in transitions)
{
Debug.WriteLine("From : " + tran.From + " To : " + tran.To);
}
}
}
// 默认为 Collapsed,所以先显示它
PaneRoot.Visibility = Visibility.Visible;
// 当在 Border 上向右滑动,并且滑动的总距离需要小于 Panel 的默认宽度。否则会脱离左侧窗口,继续向右拖动
if (e.Cumulative.Translation.X >= 0 && e.Cumulative.Translation.X < MySplitView.OpenPaneLength)
{
CompositeTransform ct = PaneRoot.RenderTransform as CompositeTransform;
ct.TranslateX = (e.Cumulative.Translation.X - MySplitView.OpenPaneLength);
}
}
}
private void Border_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
e.Handled = true;
// 仅当 SplitView 处于 Overlay 模式时(窗口宽度最小时)
if (MySplitView.DisplayMode == SplitViewDisplayMode.Overlay && PaneRoot != null)
{
// 因为当 IsPaneOpen 为 true 时,会通过 VisualStateManager 把 PaneRoot.Visibility 设置为
// Visibility.Visible,所以这里把它改为 Visibility.Collapsed,以回到初始状态
PaneRoot.Visibility = Visibility.Collapsed;
// 恢复初始状态
CompositeTransform ct = PaneRoot.RenderTransform as CompositeTransform;
// 如果大于 MySplitView.OpenPaneLength 宽度的 1/2 ,则显示,否则隐藏
if ((MySplitView.OpenPaneLength + ct.TranslateX) > MySplitView.OpenPaneLength / 2)
{
MySplitView.IsPaneOpen = true;
// 因为上面设置 IsPaneOpen = true 会再次播放向右滑动的动画,所以这里使用 SkipToFill()
// 方法,直接跳到动画结束状态
from_ClosedToOpenOverlayLeft_Transition?.Storyboard?.SkipToFill();
}
ct.TranslateX = 0;
}
}
#endregion
}
}
常用的视图帮助类 Utility:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
namespace SwipeableSplitView
{
/// <summary>
/// 视觉状态 工具类
/// </summary>
static partial class Utility
{
public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
int count = Windows.UI.Xaml.Media.VisualTreeHelper.GetChildrenCount(obj);
for (int i = 0; i < count; i++)
{
DependencyObject child = Windows.UI.Xaml.Media.VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
{
return (T)child;
}
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
public static VisualStateGroup FindVisualState(FrameworkElement element, string name)
{
if (element == null || string.IsNullOrWhiteSpace(name))
return null;
IList<VisualStateGroup> groups = VisualStateManager.GetVisualStateGroups(element);
foreach (var group in groups)
{
if (group.Name == name)
return group;
}
return null;
}
}
}
完。
来源:https://www.cnblogs.com/hebeiDGL/p/4775377.html
