跳到主要内容

github/tai

公开

Tai · Windows 软件与网站使用时长统计。上游 Planshit/Tai 的源码镜像,非灵栈原创;MIT 许可。来源:https://github.com/Planshit/Tai 。本次为手动同步,暂不提供安装包。

浏览文件

PageContainer.cs

370 行 · 12.6 KB历史下载
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7using System.Windows;
8using System.Windows.Controls;
9using System.Windows.Input;
10using System.Windows.Media;
11using System.Windows.Media.Animation;
12using System.Windows.Navigation;
13using UI.Controls.Models;
14using UI.Models;
15
16namespace UI.Controls
17{
18 public class PageContainer : Control
19 {
20 #region 依赖属性
21 public List<string> IndexUriList
22 {
23 get { return (List<string>)GetValue(IndexUriListProperty); }
24 set { SetValue(IndexUriListProperty, value); }
25 }
26 public static readonly DependencyProperty IndexUriListProperty =
27 DependencyProperty.Register("IndexUriList", typeof(List<string>), typeof(PageContainer));
28
29 public string Title
30 {
31 get { return (string)GetValue(TitleProperty); }
32 set { SetValue(TitleProperty, value); }
33 }
34 public static readonly DependencyProperty TitleProperty =
35 DependencyProperty.Register("Title",
36 typeof(string),
37 typeof(PageContainer));
38
39 public IServiceProvider ServiceProvider
40 {
41 get { return (IServiceProvider)GetValue(ServiceProviderProperty); }
42 set { SetValue(ServiceProviderProperty, value); }
43 }
44 public static readonly DependencyProperty ServiceProviderProperty =
45 DependencyProperty.Register("ServiceProvider", typeof(IServiceProvider), typeof(PageContainer));
46
47 public object Content
48 {
49 get { return (object)GetValue(ContentProperty); }
50 set { SetValue(ContentProperty, value); }
51 }
52 public static readonly DependencyProperty ContentProperty =
53 DependencyProperty.Register("Content", typeof(object), typeof(PageContainer), new PropertyMetadata("Content undefined!"));
54
55 public string Uri
56 {
57 get { return (string)GetValue(UriProperty); }
58 set { SetValue(UriProperty, value); }
59 }
60 public static readonly DependencyProperty UriProperty =
61 DependencyProperty.Register("Uri", typeof(string), typeof(PageContainer), new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnUriChanged)));
62
63 private static void OnUriChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
64 {
65 var control = d as PageContainer;
66 if (e.NewValue != e.OldValue)
67 {
68 string oldUri = e.OldValue.ToString();
69 if (control.PageCache.ContainsKey(oldUri))
70 {
71 PageModel page = control.PageCache[oldUri];
72 page.ScrollValue = control.ScrollViewer.VerticalOffset;
73 }
74 control.LoadPage();
75 }
76 }
77
78 public bool IsShowTilteBar
79 {
80 get { return (bool)GetValue(IsShowTilteBarProperty); }
81 set { SetValue(IsShowTilteBarProperty, value); }
82 }
83 public static readonly DependencyProperty IsShowTilteBarProperty =
84 DependencyProperty.Register("IsShowTilteBar",
85 typeof(bool),
86 typeof(PageContainer), new PropertyMetadata(false, new PropertyChangedCallback(OnIsShowTitleBarChanged)));
87
88 private static void OnIsShowTitleBarChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
89 {
90 var control = d as PageContainer;
91 if (e.NewValue != e.OldValue)
92 {
93 control.TitleBarVisibility = control.IsShowTilteBar ? Visibility.Visible : Visibility.Collapsed;
94 }
95 }
96 public Visibility TitleBarVisibility
97 {
98 get { return (Visibility)GetValue(TitleBarVisibilityProperty); }
99 set { SetValue(TitleBarVisibilityProperty, value); }
100 }
101 public static readonly DependencyProperty TitleBarVisibilityProperty =
102 DependencyProperty.Register("TitleBarVisibility",
103 typeof(Visibility),
104 typeof(PageContainer), new PropertyMetadata(Visibility.Collapsed));
105
106 public Command BackCommand
107 {
108 get { return (Command)GetValue(BackCommandProperty); }
109 set { SetValue(BackCommandProperty, value); }
110 }
111 public static readonly DependencyProperty BackCommandProperty =
112 DependencyProperty.Register("BackCommand",
113 typeof(Command),
114 typeof(PageContainer));
115
116
117 public PageContainer Instance { get { return (PageContainer)GetValue(InstanceProperty); } set { SetValue(InstanceProperty, value); } }
118
119 public static readonly DependencyProperty InstanceProperty = DependencyProperty.Register("Instance", typeof(PageContainer), typeof(PageContainer));
120 #endregion
121
122 /// <summary>
123 /// 加载页面完成后发生
124 /// </summary>
125 public event EventHandler OnLoadPaged;
126
127 private readonly string ProjectName;
128 private List<string> Historys;
129 public int Index = 0, OldIndex = 0;
130 private Dictionary<string, PageModel> PageCache;
131 private bool IsBack = false;
132 private ScrollViewer ScrollViewer;
133 private Frame Frame;
134 public PageContainer()
135 {
136 DefaultStyleKey = typeof(PageContainer);
137 ProjectName = "UI";
138 Historys = new List<string>();
139 BackCommand = new Command(new Action<object>(OnBackCommand));
140 NavigationCommands.BrowseBack.InputGestures.Clear();
141 NavigationCommands.BrowseForward.InputGestures.Clear();
142 PageCache = new Dictionary<string, PageModel>();
143
144 CreateAnimations();
145 }
146
147
148 public override void OnApplyTemplate()
149 {
150 base.OnApplyTemplate();
151
152 ScrollViewer = GetTemplateChild("ScrollViewer") as ScrollViewer;
153 Frame = GetTemplateChild("Frame") as Frame;
154 Frame.NavigationService.Navigated += NavigationService_Navigated;
155 Frame.NavigationService.LoadCompleted += NavigationService_LoadCompleted;
156 Loaded += PageContainer_Loaded;
157 }
158
159 private void NavigationService_LoadCompleted(object sender, NavigationEventArgs e)
160 {
161 animation.Begin();
162 }
163
164 private void NavigationService_Navigated(object sender, NavigationEventArgs e)
165 {
166 Frame.NavigationService.RemoveBackEntry();
167 }
168
169 private void PageContainer_Loaded(object sender, RoutedEventArgs e)
170 {
171 Instance = this;
172 }
173
174 protected override void OnMouseDown(MouseButtonEventArgs e)
175 {
176 base.OnMouseDown(e);
177 if (e.ChangedButton == MouseButton.XButton1)
178 {
179 Back();
180 }
181 }
182 private void OnBackCommand(object obj)
183 {
184 Back();
185 }
186
187 public void Back()
188 {
189 if (Index - 1 >= 0)
190 {
191 OldIndex = Index;
192 Index--;
193 string uri = Historys[Index];
194
195 int preIndex = Index + 1;
196
197 // 从缓存中移除上一页
198
199 var pageUri = Historys[preIndex];
200 if (PageCache.ContainsKey(pageUri))
201 {
202 var page = PageCache[pageUri];
203 var vm = page.Instance.DataContext as ModelBase;
204 vm?.Dispose();
205 page.Instance.Content = null;
206 page.Instance.DataContext = null;
207
208 PageCache.Remove(pageUri);
209 }
210 Historys.RemoveRange(preIndex, 1);
211
212 IsBack = true;
213
214 Uri = uri;
215
216 }
217 }
218
219 public void ClearHistorys()
220 {
221 Historys.Clear();
222 }
223 private void LoadPage()
224 {
225 if (Uri != string.Empty)
226 {
227 if (IndexUriList != null && IndexUriList.Contains(Uri))
228 {
229 Historys.Clear();
230 Index = 0;
231 OldIndex = 0;
232 Historys.Add(Uri);
233 if (!IsBack)
234 {
235 ClearCache();
236 }
237 }
238 else
239 {
240 //处理历史记录
241 if (OldIndex == Index)
242 {
243 //新开
244 Historys.Add(Uri);
245 Index++;
246 }
247 OldIndex = Index;
248 }
249 PageModel page = GetPage();
250
251
252 if (page != null)
253 {
254 Content = page.Instance;
255
256 // 加入缓存
257 if (!PageCache.ContainsKey(Uri))
258 {
259 PageCache.Add(Uri, page);
260 }
261
262 // 滚动条位置处理
263 if (IsBack)
264 {
265 ScrollViewer.ScrollToVerticalOffset(page.ScrollValue);
266 }
267 else
268 {
269 ScrollViewer?.ScrollToVerticalOffset(0);
270 }
271
272 OnLoadPaged?.Invoke(this, EventArgs.Empty);
273 }
274 else
275 {
276 Debug.WriteLine("找不到Page:" + Uri + ",请确认已被注入");
277 }
278 }
279 IsBack = false;
280 }
281
282 private PageModel GetPage()
283 {
284 Page page = null;
285 if (PageCache.ContainsKey(Uri))
286 {
287 return PageCache[Uri];
288 }
289 Type pageType = Type.GetType(ProjectName + ".Views." + Uri);
290 if (pageType != null && ServiceProvider != null)
291 {
292 page = ServiceProvider.GetService(pageType) as Page;
293 }
294 var newPage = new PageModel()
295 {
296 Instance = page,
297 ScrollValue = 0
298 };
299
300 return newPage;
301 }
302
303 private void ClearCache()
304 {
305 if (PageCache != null)
306 {
307 foreach (var key in PageCache.Keys)
308 {
309 var page = PageCache[key];
310 var vm = page.Instance.DataContext as ModelBase;
311 vm?.Dispose();
312 page.Instance.Content = null;
313 page.Instance.DataContext = null;
314 }
315 PageCache.Clear();
316 }
317 }
318
319 public void Disponse()
320 {
321 ClearCache();
322 Content = null;
323 DataContext = null;
324 Instance = null;
325 }
326
327 private Storyboard animation;
328 private void CreateAnimations()
329 {
330 ClipToBounds = true;
331
332 ScaleTransform scaleTransform = new ScaleTransform();
333 TranslateTransform translateTransform = new TranslateTransform();
334
335 TransformGroup tfg = new TransformGroup();
336 tfg.Children.Add(scaleTransform);
337 tfg.Children.Add(translateTransform);
338 RenderTransform = tfg;
339 RenderTransformOrigin = new Point(.5, .5);
340
341 animation = new Storyboard();
342
343 DoubleAnimation scrollAnimation = new DoubleAnimation();
344 scrollAnimation.From = 50;
345 scrollAnimation.To = 0;
346 scrollAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.14));
347
348 Storyboard.SetTarget(scrollAnimation, this);
349 Storyboard.SetTargetProperty(scrollAnimation, new PropertyPath("RenderTransform.Children[1].Y"));
350 animation.Children.Add(scrollAnimation);
351 //DoubleAnimation scaleXAnimation = new DoubleAnimation();
352 //scaleXAnimation.From = .8;
353 //scaleXAnimation.To = 1;
354 //scaleXAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.14));
355
356 //DoubleAnimation scaleYAnimation = new DoubleAnimation();
357 //scaleYAnimation.From = .8;
358 //scaleYAnimation.To = 1;
359 //scaleYAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.14));
360
361 //Storyboard.SetTarget(scaleXAnimation, this);
362 //Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath("RenderTransform.Children[0].ScaleX"));
363 //Storyboard.SetTarget(scaleYAnimation, this);
364 //Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath("RenderTransform.Children[0].ScaleY"));
365
366 //animation.Children.Add(scaleXAnimation);
367 //animation.Children.Add(scaleYAnimation);
368 }
369 }
370}