1. 程式人生 > 其它 >C#技術棧入門到精通系列10A——WPF下的MVVM實現

C#技術棧入門到精通系列10A——WPF下的MVVM實現

閱讀目錄

1、介紹
2、核心搭建Core
3、框架完善
  3.1、基礎資料繫結
  3.2、事件繫結
  3.3、轉換器使用
  3.4、新增日誌頁
  3.5、模型業務呼叫
  3.6、切換可視頁面
  3.7、查詢資料分頁顯示
4、框架使用
5、參考

返回系列文章目錄 

 

案例程式碼下載

 1、介紹

  MVVM(Model-View-ViewModel)是一種驅動視覺化介面的事件為起點的軟體架構模式,個人認為其是MVC的升級版。

上圖是我們MVVM架構的組成,主要模組職責如下:

①Infrastructure:給MVVM模組做基礎支援,存放一些資料獲取模組,幫助模組,轉換器和支援框架的檔案。

②Models:是MVVM框架的業務處理部分,主要的業務邏輯都存放在這個模組。

③Views:存放和使用者互動的相關視窗、頁面和控制元件。

④ViewModels:主要是介面展示需要用到的資料,介面上命令的執行邏輯,呼叫Models模組業務。


2、核心搭建Core

  我們這個框架的原理就是,Views對ViewModel屬性的雙向繫結 binding ,ViewModel資料更改後通知Views利用的是 INotifyPropertyChanged 介面。下面開始來搭建框架:

①先建立一個 WPF應用程式 Demo10A-Framework ,這就是框架的主要部分,Views 存放介面部分,主要存放Window、Page、UserControl及一些自定義的控制元件;ViewModels

存放介面互動的資料監聽事件。

②分別建立框架的另外兩個模組,選擇 WPF類庫 分別命名Demo10A-Models和Demo10A-Infrastructure。

③模組 Demo10A-Framework 裡建立資料夾 Core,資料夾下建立ViewModel資料變更通知類NotificationObject.cs。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Linq;
 5 using System.Runtime.CompilerServices;
6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace Demo10A_Framework.Core 10 { 11 public class NotificationObject : INotifyPropertyChanged 12 { 13 public event PropertyChangedEventHandler PropertyChanged; 14 public void RaisePropertyChanged([CallerMemberName] string propertyName = "") 15 { 16 this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 17 } 18 } 19 }
NotificationObject.cs

④模組 Demo10A-Framework 資料夾 Core 下建立跨執行緒幫助類DispatcherHelper.cs。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows;
 7 using System.Windows.Threading;
 8 
 9 namespace Demo10A_Framework.Core
10 {
11     public class DispatcherHelper
12     {
13         public static Dispatcher GetUIDispatcher()
14         {
15             try
16             {
17                 return Application.Current.MainWindow.Dispatcher;
18             }
19             catch
20             {
21                 return null;
22             }
23         }
24     }
25 }
DispatcherHelper.cs

⑤模組 Demo10A-Framework 資料夾 Core 下建立非同步執行緒操作、訊息彈窗、窗體操作和反射建立View的基礎ViewModel類BaseViewModel.cs。

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Reflection;
  5 using System.Text;
  6 using System.Threading.Tasks;
  7 using System.Windows;
  8 using System.Windows.Controls;
  9 using System.Windows.Threading;
 10 
 11 namespace Demo10A_Framework.Core
 12 {
 13     public class BaseViewModel : NotificationObject
 14     {
 15         #region 基礎屬性
 16         private static string _viewsAssemblyName;//Views程式集名
 17         private static string _viewsNamespace;//Views名稱空間
 18         private Window _windowMain; //主窗體  
 19         public EventHandler CloseCallBack = null; //窗體/頁面/控制元件 關閉委託 
 20         public FrameworkElement UIElement { get; set; } //UI元素 
 21         #endregion
 22 
 23         #region 建構函式
 24         public BaseViewModel()
 25         {
 26             _windowMain = Application.Current.MainWindow;
 27             SetUIElement();
 28 
 29             //資料繫結
 30             UIElement.DataContext = this;
 31         }
 32         public BaseViewModel(string viewsAssemblyName, string viewsNamespace)
 33         {
 34             _viewsAssemblyName = viewsAssemblyName;
 35             _viewsNamespace = viewsNamespace; 
 36             
 37             _windowMain = Application.Current.MainWindow;
 38             SetUIElement();
 39 
 40             //資料繫結
 41             UIElement.DataContext = this;
 42         }
 43         #endregion
 44 
 45         #region 通過反射建立對應的UI元素
 46         public void SetUIElement()
 47         {
 48             Type childType = this.GetType();//獲取子類的型別   
 49             var name = childType.Name;
 50             name = name.Replace("Model", "");
 51             switch (name.First())
 52             {
 53                 case 'W':
 54                     UIElement = GetElement<Window>(name);
 55                     (UIElement as Window).Closing += (s, e) =>
 56                     {
 57                         if (CloseCallBack != null)
 58                         {
 59                             CloseCallBack(s, e);
 60                         }
 61                     };
 62                     break;
 63                 case 'P':
 64                     UIElement = GetElement<Page>(name);
 65                     (UIElement as Page).Unloaded += (s, e) =>
 66                     {
 67                         if (CloseCallBack != null)
 68                         {
 69                             CloseCallBack(s, e);
 70                         }
 71                     };
 72                     break;
 73                 case 'U':
 74                     UIElement = GetElement<UserControl>(name);
 75                     (UIElement as UserControl).Unloaded += (s, e) =>
 76                     {
 77                         if (CloseCallBack != null)
 78                         {
 79                             CloseCallBack(s, e);
 80                         }
 81                     };
 82                     break;
 83                 default:
 84                     throw new Exception("元素名不規範");
 85 
 86             }
 87 
 88 
 89 
 90         }
 91 
 92         public E GetElement<E>(string elementName)
 93         {
 94             Type type = GetFormType(_viewsNamespace + "." + elementName);
 95             E element = (E)Activator.CreateInstance(type);
 96             return element;
 97         }
 98 
 99         public Type GetFormType(string fullName)
100         {
101             Assembly assembly = Assembly.Load(_viewsAssemblyName);
102             Type type = assembly.GetType(fullName, true, false);
103             return type;
104         }
105         #endregion
106 
107         #region 窗體操作
108         public void Show()
109         {
110             if (UIElement is Window)
111             {
112                 (UIElement as Window).Show();
113             }
114             else
115             {
116                 throw new Exception("元素型別不正確");
117             }
118         }
119 
120         public void ShowDialog()
121         {
122             if (UIElement is Window)
123             {
124                 (UIElement as Window).ShowDialog();
125             }
126             else
127             {
128                 throw new Exception("元素型別不正確");
129             }
130         }
131 
132         public void Close()
133         {
134             if (UIElement is Window)
135             {
136                 (UIElement as Window).Close();
137             }
138             else
139             {
140                 throw new Exception("元素型別不正確");
141             }
142         }
143 
144         public void Hide()
145         {
146             if (UIElement is Window)
147             {
148                 (UIElement as Window).Hide();
149             }
150             else
151             {
152                 throw new Exception("元素型別不正確");
153             }
154         }
155         #endregion
156 
157         #region   非同步執行緒
158         public void AsyncLoad(Action action)
159         {
160             IAsyncResult result = action.BeginInvoke((iar) =>
161             {
162             }, null);
163         }
164 
165         public void AsyncLoad(Action action, Action callback)
166         {
167             IAsyncResult result = action.BeginInvoke((iar) =>
168             {
169                 this.DoMenthodByDispatcher(callback);
170             }, null);
171         }
172 
173         public void AsyncLoad<T>(Action<T> action, T para, Action callback)
174         {
175             IAsyncResult result = action.BeginInvoke(para, (iar) =>
176             {
177                 this.DoMenthodByDispatcher(callback);
178             }, null);
179         }
180 
181         public void AsyncLoad<T, R>(Func<T, R> action, T para, Action<R> callback)
182         {
183             IAsyncResult result = action.BeginInvoke(para, (iar) =>
184             {
185                 var res = action.EndInvoke(iar);
186                 this.DoMenthodByDispatcher<R>(callback, res);
187             }, null);
188         }
189 
190         public void AsyncLoad<R>(Func<R> action, Action<R> callback)
191         {
192             IAsyncResult result = action.BeginInvoke((iar) =>
193             {
194                 var res = action.EndInvoke(iar);
195                 this.DoMenthodByDispatcher<R>(callback, res);
196             }, null);
197         }
198 
199         public void DoMenthodByDispatcher<T>(Action<T> action, T obj)
200         {
201             DispatcherHelper.GetUIDispatcher().BeginInvoke(new Action(() =>
202             {
203                 action(obj);
204             }), DispatcherPriority.Normal);
205         }
206 
207         public void DoMenthodByDispatcher(Action action)
208         {
209             DispatcherHelper.GetUIDispatcher().BeginInvoke(new Action(() =>
210             {
211                 action();
212             }), DispatcherPriority.Normal);
213         }
214         #endregion
215 
216         #region Message
217         public void MessageBox(Window owner, string msg)
218         {
219             DispatcherHelper.GetUIDispatcher().Invoke(new Action(() =>
220             {
221                 if (owner != null)
222                 {
223                     System.Windows.MessageBox.Show(owner, msg, "提示資訊");
224                 }
225                 else
226                 {
227                     System.Windows.MessageBox.Show(_windowMain, msg, "提示資訊");
228                 }
229             }));
230         }
231 
232         public void MessageBox(string msg)
233         {
234             DispatcherHelper.GetUIDispatcher().Invoke(new Action(() =>
235             {
236                 System.Windows.MessageBox.Show(_windowMain, msg, "提示資訊");
237             }));
238         }
239 
240         public void MessageBox(string msg, string strTitle)
241         {
242             DispatcherHelper.GetUIDispatcher().Invoke(new Action(() =>
243             {
244                 System.Windows.MessageBox.Show(_windowMain, msg, "提示資訊");
245             }));
246         }
247 
248         public void MessageBox(string msg, Action<bool> callback)
249         {
250             MessageBox("系統提示", msg, callback);
251         }
252 
253         public void MessageBox(string title, string msg, Action<bool> callback)
254         {
255             DispatcherHelper.GetUIDispatcher().Invoke(new Action(() =>
256             {
257                 if (System.Windows.MessageBox.Show(_windowMain, msg, title, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
258                 {
259                     callback(true);
260                 }
261                 else
262                 {
263                     callback(false);
264                 }
265             }));
266         }
267         #endregion
268 
269     }
270 }
BaseViewModel.cs

⑥模組 Demo10A-Framework 資料夾 ViewModels 下建立歡迎頁的ViewModel,WMainViewModel.cs。

 1 using Demo10A_Framework.Core;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace Demo10A_Framework.ViewModels
 9 {
10     public class WMainViewModel:BaseViewModel
11     {
12         public WMainViewModel(string pAssemblyName, string pNamespace):base(pAssemblyName, pNamespace)
13         {
14             
15         }
16     }
17 }
WMainViewModel.cs

⑦模組 Demo10A-Framework 資料夾 Views 下刪除預設建立的主窗體MainWindow.xaml,新建項 視窗(WPF) 命名為 WMainView.xaml,開啟App.xaml檔案,刪除XAML裡引匯入口程式碼 StartupUri="MainWindow.xaml" ,開啟 App.xaml.cs ,新增引導程式碼及掛機全域性異常處理的程式碼如下。

 1 using Demo10A_Framework.Globals;
 2 using Demo10A_Framework.ViewModels;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Configuration;
 6 using System.Data;
 7 using System.Linq;
 8 using System.Threading.Tasks;
 9 using System.Windows;
10 using System.Windows.Threading;
11 
12 namespace Demo10A_Framework
13 {
14     /// <summary>
15     /// App.xaml 的互動邏輯
16     /// </summary>
17     public partial class App : Application
18     {
19         protected override void OnStartup(StartupEventArgs e)
20         {
21             //配置專案的程式集名和名稱空間,利用反射建立窗體
22             var mainViewModel = new WMainViewModel("Demo10A-Framework", "Demo10A_Framework.Views");
23             GlobalVisualizedData.MainViewModel = mainViewModel;  //儲存到全域性變數
24             Application.Current.MainWindow = mainViewModel.UIElement as Window;
25             mainViewModel.Show();
26             base.OnStartup(e);
27         }
28 
29         /// <summary>
30         /// 載入完成
31         /// </summary>
32         /// <param name="e"></param>
33         protected override void OnLoadCompleted(System.Windows.Navigation.NavigationEventArgs e)
34         {
35             base.OnLoadCompleted(e);
36             Current.DispatcherUnhandledException += App_OnDispatcherUnhandledException;
37             AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
38         }
39 
40         /// <summary>
41         /// UI執行緒丟擲全域性異常事件處理
42         /// </summary>
43         /// <param name="sender"></param>
44         /// <param name="e"></param>
45         private void App_OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
46         {
47             try
48             {
49                 e.Handled = true;
50             }
51             catch (Exception ex)
52             {
53             }
54         }
55 
56         /// <summary>
57         /// 非UI執行緒丟擲全域性異常事件處理
58         /// </summary>
59         /// <param name="sender"></param>
60         /// <param name="e"></param>
61         private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
62         {
63             try
64             {
65                 var exception = e.ExceptionObject as Exception;
66                 if (exception != null)
67                 {
68                 }
69             }
70             catch (Exception ex)
71             {
72             }
73         }
74     }
75 }
App.xaml.cs
1 <Application x:Class="Demo10A_Framework.App"
2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4              xmlns:local="clr-namespace:Demo10A_Framework"
5              >
6     <Application.Resources>
7          
8     </Application.Resources>
9 </Application>
App.xaml
 1 <Window x:Class="Demo10A_Framework.Views.WMainView"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:Demo10A_Framework.Views"
 7         mc:Ignorable="d"
 8         Title="WMainView" Height="450" Width="800">
 9     <Grid>
10         <Frame x:Name="mainFrame" NavigationUIVisibility="Hidden"/>
11     </Grid>
12 </Window>
WMainView.xaml

⑧模組 Demo10A-Framework 資料夾 Globals 下建立GlobalVisualizedData.cs,用來存放ViewModel直接操作View裡面的元素邏輯。

 1 using Demo10A_Framework.ViewModels;
 2 using Demo10A_Framework.Views;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8 
 9 namespace Demo10A_Framework.Globals
10 {
11     public class GlobalVisualizedData
12     {
13         #region 全域性主視窗ViewModel + public static WMainViewModel MainViewModel
14         private static WMainViewModel _mainViewModel;
15 
16         public static WMainViewModel MainViewModel
17         {
18             get { return _mainViewModel; }
19             set {
20                 _mainView = value.UIElement as WMainView;
21                 _mainViewModel = value; }
22         }
23         #endregion
24 
25         private static WMainView _mainView; //全域性主視窗View
26 
27 
28     }
29 }
GlobalVisualizedData.cs

⑨以上就已經完成了WPF下MVVM框架的核心程式碼,可以嘗試執行一下。

 

3、框架完善

  經過上面的步驟,基本的MVVM框架已經成型,以後我們就可以在這個框架上開發應用程式了,我建議可以做成SPA(單頁面)應用,這樣可以降低頁面切換的很多額外工作。
3.1、基礎資料繫結

   這節我們來給框架建立一個歡迎視窗,歡迎介面3秒後自動關閉。

①模組 Demo10A-Framework 資料夾 ViewModels 下建立歡迎頁的ViewModel,WWelcomeViewModel.cs。

 1 using Demo10A_Framework.Core;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace Demo10A_Framework.ViewModels
 9 {
10     public class WWelcomeViewModel:BaseViewModel
11     {
12         public WWelcomeViewModel()
13         {
14         }
15         public WWelcomeViewModel(string viewsAssemblyName, string viewsNamespace) : base(viewsAssemblyName, viewsNamespace)
16         {
17         }
18     }
19 }
WWelcomeViewModel.cs

②模組 Demo10A-Framework 資料夾 Views 下建立歡迎頁的View,WWelcomeView.xaml。

 1 <Window x:Class="Demo10A_Framework.Views.WWelcomeView"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:Demo10A_Framework.Views"
 7         mc:Ignorable="d"
 8         Title="WWelcomeView" Height="450" Width="800" WindowStyle="None" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" Cursor="Hand" >
 9     <Grid VerticalAlignment="Center" HorizontalAlignment="Center">
10         <TextBlock Text="歡迎頁" FontSize="72"/>
11     </Grid>
12 </Window>
WWelcomeView.xaml

③模組 Demo10A-Framework 資料夾 Globals 下更新GlobalVisualizedData.cs,加入更新主窗體標題的。

 1 using Demo10A_Framework.ViewModels;
 2 using Demo10A_Framework.Views;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading;
 8 using System.Threading.Tasks;
 9 using System.Windows;
10 
11 namespace Demo10A_Framework.Globals
12 {
13     public class GlobalVisualizedData
14     {
15         private const string _viewsAssemblyName = "Demo10A-Framework";
16         private const string _viewsNamespace = "Demo10A_Framework.Views";
17         private static WMainViewModel _mainViewModel; //全域性主視窗ViewModel
18         private static WMainView _mainWindowView; //全域性主視窗View
19 
20         public static void UseWelcomeWindow(bool isUseWelcomeWindow,int delayMilliseconds)
21         {
22             if (isUseWelcomeWindow)
23             {
24                 _mainViewModel = new WMainViewModel(_viewsAssemblyName, _viewsNamespace);
25                 _mainWindowView = _mainViewModel.UIElement as WMainView;
26                 var welcome = new WWelcomeViewModel();
27                 welcome.Show();
28                 App.Current.Dispatcher.Invoke(() =>
29                 {  //跨執行緒操作UI
30                     Task.WaitAll(Task.Delay(delayMilliseconds));
31                     welcome.Close();
32                     _mainViewModel.Show();
33                 });
34             }
35             else
36             {
37                 _mainViewModel = new WMainViewModel(_viewsAssemblyName, _viewsNamespace);
38                 _mainWindowView = _mainViewModel.UIElement as WMainView;
39                 _mainViewModel.Show();
40             }
41         }
42     }
43 }
GlobalVisualizedData.cs

④模組 Demo10A-Framework 下檔案App.xaml.cs,修改頁面啟動管理用GlobalVisualizedData控制。

 1 using Demo10A_Framework.Globals;
 2 using Demo10A_Framework.ViewModels;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Configuration;
 6 using System.Data;
 7 using System.Linq;
 8 using System.Threading.Tasks;
 9 using System.Windows;
10 using System.Windows.Threading;
11 
12 namespace Demo10A_Framework
13 {
14     /// <summary>
15     /// App.xaml 的互動邏輯
16     /// </summary>
17     public partial class App : Application
18     {
19         protected override void OnStartup(StartupEventArgs e)
20         {
21             GlobalVisualizedData.UseWelcomeWindow(true,3000);  //初始化配置
22             base.OnStartup(e);
23         }
24 
25         /// <summary>
26         /// 載入完成
27         /// </summary>
28         /// <param name="e"></param>
29         protected override void OnLoadCompleted(System.Windows.Navigation.NavigationEventArgs e)
30         {
31             base.OnLoadCompleted(e);
32             Current.DispatcherUnhandledException += App_OnDispatcherUnhandledException;
33             AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
34         }
35 
36         /// <summary>
37         /// UI執行緒丟擲全域性異常事件處理
38         /// </summary>
39         /// <param name="sender"></param>
40         /// <param name="e"></param>
41         private void App_OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
42         {
43             try
44             {
45                 e.Handled = true;
46             }
47             catch (Exception ex)
48             {
49             }
50         }
51 
52         /// <summary>
53         /// 非UI執行緒丟擲全域性異常事件處理
54         /// </summary>
55         /// <param name="sender"></param>
56         /// <param name="e"></param>
57         private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
58         {
59             try
60             {
61                 var exception = e.ExceptionObject as Exception;
62                 if (exception != null)
63                 {
64                 }
65             }
66             catch (Exception ex)
67             {
68             }
69         }
70     }
71 }
App.xaml.cs

⑤以上就完成了從歡迎頁停留3秒後轉入主視窗。

 

3.2、事件繫結

  這節我們來編寫事件繫結的相關程式碼,做一個按鈕按下彈出訊息框的案例。

①模組 Demo10A-Framework 資料夾 ViewModels 下建立系統頁的ViewModel,PSystemViewModel.cs。

 1 using Demo10A_Framework.Core;
 2 using Demo10A_Framework.Globals;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8 
 9 namespace Demo10A_Framework.ViewModels
10 {
11     public class PSystemViewModel:BaseViewModel
12     {
13         #region 事件-訊息框 + public DelegateCommand CallMessageBoxCommand
14         public DelegateCommand CallMessageBoxCommand
15         {
16             get
17             {
18                 return new DelegateCommand(CallMessageBoxCommand_Executed);
19             }
20         }
21 
22         private void CallMessageBoxCommand_Executed(object obj)
23         {
24             MessageBox("快捷支付多份心,莫名中獎少頓惜。 網購陷阱花樣多,線上交易要當心。", "防詐提醒");
25         }
26         #endregion
27 
28         #region 建構函式 + public PSystemViewModel()
29         public PSystemViewModel()
30         {
31             GlobalVisualizedData.SetMainWindowTitle("系統主頁[BigBox777]");
32         } 
33         #endregion
34     }
35 }
PSystemViewModel.cs

②模組 Demo10A-Framework 資料夾 Views 下建立系統頁的View,PSystemView.xaml。

 1 <Page x:Class="Demo10A_Framework.Views.PSystemView"
 2       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5       xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6       xmlns:local="clr-namespace:Demo10A_Framework.Views"
 7       mc:Ignorable="d" 
 8       d:DesignHeight="450" d:DesignWidth="800"
 9       Title="PSystemView">
10 
11     <Grid>
12         <Grid.ColumnDefinitions>
13             <ColumnDefinition Width="250"/>
14             <ColumnDefinition/>
15         </Grid.ColumnDefinitions>
16         <Border Margin="1,0,0,1" Grid.Column="0" BorderThickness="1,1,1,1" BorderBrush="Black">
17             <StackPanel>
18                 <Button Height="30" Content="彈出訊息框" Command="{Binding CallMessageBoxCommand}"/>
19                 <Button Height="30" Content="改變視窗標題"/>
20                 <Button Height="30" Content="切換頁面"/>
21                 <Button Height="30" Content="建立新視窗"/>
22                 <Button Height="30" Content="關閉新視窗"/>
23                 <Button Height="30" Content="轉換器使用"/>
24                 <Border Margin="0" Padding="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="Red">
25                     <Grid Height="80">
26                         <Grid.ColumnDefinitions>
27                             <ColumnDefinition Width="50"/>
28                             <ColumnDefinition/>
29                         </Grid.ColumnDefinitions>
30                         <Grid.RowDefinitions>
31                             <RowDefinition/>
32                             <RowDefinition/>
33                             <RowDefinition/>
34                         </Grid.RowDefinitions>
35 
36                         <TextBlock Text="使用者名稱:" VerticalAlignment="Center"/>
37                         <TextBox Text="BigBox777" Grid.Column="1" VerticalAlignment="Center"/>
38                         <TextBlock Text="密碼:" Grid.Row="1" VerticalAlignment="Center"/>
39                         <PasswordBox Password="12345" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center"/>
40                         <Button Content="登入" Grid.Row="2" Grid.ColumnSpan="2"/>
41                     </Grid>
42                 </Border>
43                 <Button Height="30" Content="分頁顯示"/>
44             </StackPanel>
45         </Border>
46         <Frame Grid.Column="1">
47             <Frame.Background>
48                 <VisualBrush Stretch="Uniform" Opacity="0.5" Viewbox="-1,-1,3,3">
49                     <VisualBrush.Visual>
50                         <TextBlock Text="BigBox777"/>
51                     </VisualBrush.Visual>
52                 </VisualBrush>
53             </Frame.Background>
54         </Frame>
55     </Grid>
56 </Page>
PSystemView.xaml

③模組 Demo10A-Framework 資料夾 Globals 下更新GlobalVisualizedData.cs,加入更新系統頁管理程式碼。

 1 using Demo10A_Framework.ViewModels;
 2 using Demo10A_Framework.Views;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading;
 8 using System.Threading.Tasks;
 9 using System.Windows;
10 
11 namespace Demo10A_Framework.Globals
12 {
13     public class GlobalVisualizedData
14     {
15         #region 常量-Views配置資訊
16         private const string _viewsAssemblyName = "Demo10A-Framework";
17         private const string _viewsNamespace = "Demo10A_Framework.Views";
18         #endregion
19         #region 全域性-ViewModel資訊
20         private static WMainViewModel _mainViewModel; //全域性主視窗ViewModel
21         private static PSystemViewModel _systemViewModel; //全域性系統頁ViewModel 
22         #endregion
23 
24         #region 使用歡迎頁 + public static void UseWelcomeWindow(bool isUseWelcomeWindow, int delayMilliseconds)
25         public static void UseWelcomeWindow(bool isUseWelcomeWindow, int delayMilliseconds)
26         {
27             if (isUseWelcomeWindow)
28             {
29                 _mainViewModel = new WMainViewModel(_viewsAssemblyName, _viewsNamespace);
30                 var welcome = new WWelcomeViewModel();
31                 welcome.Show();
32                 App.Current.Dispatcher.Invoke(() =>
33                 {  //跨執行緒操作UI
34                     Task.WaitAll(Task.Delay(delayMilliseconds));
35                     welcome.Close();
36                     ShowMainView();
37                 });
38             }
39             else
40             {
41                 _mainViewModel = new WMainViewModel(_viewsAssemblyName, _viewsNamespace);
42                 ShowMainView();
43             }
44 
45         }
46         private static void ShowMainView()
47         {
48             _mainViewModel.Show();
49             _systemViewModel = new PSystemViewModel();
50             _mainViewModel.MainFrameNavigation(_systemViewModel.UIElement as PSystemView);
51         }
52         #endregion
53 
54         #region 設定主窗體標題 + public static void SetMainWindowTitle(string title)
55         public static void SetMainWindowTitle(string title)
56         {
57             _mainViewModel.WindowTitle = title;
58         } 
59         #endregion
60 
61 
62     }
63 }
GlobalVisualizedData.cs

④以上就完成了按鈕按下彈出訊息框的案例。

 

3.3、轉換器使用

①模組 Demo10A-Framework 資料夾 Converters 下建立需要使用的轉換器程式碼ConvertChangeState2EllipseFill.cs。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Globalization;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 using System.Windows;
 8 using System.Windows.Data;
 9 using System.Windows.Media;
10 
11 namespace Demo10A_Framework.Converters
12 {
13     public class ConvertChangeState2EllipseFill : IValueConverter
14     {
15         //當值從繫結源傳播給繫結目標時,呼叫方法Convert
16         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
17         {
18             if (value == null || !(value is bool))
19             {
20                 throw new Exception();
21             }
22             else
23             {
24                 var state = (bool)value;
25                 var str = parameter as string;
26                 if (state)
27                 {
28                     if (str == "1")
29                     {
30                         return Brushes.Red;
31                     }
32                     else if (str == "2")
33                     {
34                         return Brushes.Blue;
35                     }
36                     else
37                     {
38                         return Brushes.Yellow;
39                     }
40                 }
41                 else
42                 {
43                     if (str == "1")
44                     {
45                         return Brushes.Orange;
46                     }
47                     else if (str == "2")
48                     {
49                         return Brushes.DeepSkyBlue;
50                     }
51                     else
52                     {
53                         return Brushes.YellowGreen;
54                     }
55                 }
56 
57             }
58 
59         }
60 
61         //當值從繫結目標傳播給繫結源時,呼叫此方法ConvertBack
62         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
63         {
64             return DependencyProperty.UnsetValue;
65         }
66     }
67 }
ConvertChangeState2EllipseFill.cs

②模組 Demo10A-Framework 資料夾 Views 下更新系統頁的View,PSystemView.xaml。

 1 <Page x:Class="Demo10A_Framework.Views.PSystemView"
 2       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5       xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6       xmlns:local="clr-namespace:Demo10A_Framework.Views" xmlns:converters="clr-namespace:Demo10A_Framework.Converters"
 7       mc:Ignorable="d" 
 8       d:DesignHeight="450" d:DesignWidth="800"
 9       Title="PSystemView">
10     <Page.Resources>
11         <converters:ConvertChangeState2EllipseFill x:Key="changeStateConvert"/>
12     </Page.Resources>
13     <Grid>
14         <Grid.ColumnDefinitions>
15             <ColumnDefinition Width="250"/>
16             <ColumnDefinition/>
17         </Grid.ColumnDefinitions>
18         <Border Margin="1,0,0,1" Grid.Column="0" BorderThickness="1,1,1,1" BorderBrush="Black">
19             <StackPanel>
20                 <Button Height="30" Content="彈出訊息框" Command="{Binding CallMessageBoxCommand}"/>
21                 <Border Margin="0" Padding="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="Red">
22                     <Grid Height="60">
23                         <Grid.ColumnDefinitions>
24                             <ColumnDefinition Width="60"/>
25                             <ColumnDefinition/>
26                         </Grid.ColumnDefinitions>
27                         <Grid.RowDefinitions>
28                             <RowDefinition/>
29                             <RowDefinition/>
30                         </Grid.RowDefinitions>
31                         <TextBlock Text="視窗標題:" VerticalAlignment="Center"/>
32                         <TextBox Text="{Binding SystemTitle}" Grid.Column="1" VerticalAlignment="Center"/>
33                         <Button Content="改變視窗標題" Command="{Binding ChangeWindowTitleCommand}" Grid.Row="1" Grid.ColumnSpan="2"/>
34                     </Grid>
35                 </Border>
36                 <Border Margin="0" Padding="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="Red">
37                     <Grid Height="60">
38                         <Grid.RowDefinitions>
39                             <RowDefinition/>
40                             <RowDefinition/>
41                         </Grid.RowDefinitions>
42                         <StackPanel Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal">
43                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert}}" Margin="0,0,5,0"/>
44                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert}}" Margin="0,0,5,0"/>
45                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='1'}" Margin="0,0,5,0"/>
46                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='1'}" Margin="0,0,5,0"/>
47                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='2'}" Margin="0,0,5,0"/>
48                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='2'}" Margin="0,0,5,0"/>
49                         </StackPanel>
50                         <Button Content="轉換器使用" Command="{Binding UseConverterCommand}" Grid.Row="1" Grid.ColumnSpan="2"/>
51                     </Grid>
52                 </Border>
53                 <Button Height="30" Content="切換頁面"/>
54                 <Button Height="30" Content="建立新視窗"/>
55                 <Button Height="30" Content="關閉新視窗"/>
56                 <Border Margin="0" Padding="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="Red">
57                     <Grid Height="80">
58                         <Grid.ColumnDefinitions>
59                             <ColumnDefinition Width="60"/>
60                             <ColumnDefinition/>
61                         </Grid.ColumnDefinitions>
62                         <Grid.RowDefinitions>
63                             <RowDefinition/>
64                             <RowDefinition/>
65                             <RowDefinition/>
66                         </Grid.RowDefinitions>
67 
68                         <TextBlock Text="使用者名稱:" VerticalAlignment="Center"/>
69                         <TextBox Text="BigBox777" Grid.Column="1" VerticalAlignment="Center"/>
70                         <TextBlock Text="密碼:" Grid.Row="1" VerticalAlignment="Center"/>
71                         <PasswordBox Password="12345" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center"/>
72                         <Button Content="登入" Grid.Row="2" Grid.ColumnSpan="2"/>
73                     </Grid>
74                 </Border>
75                 <Button Height="30" Content="分頁顯示"/>
76             </StackPanel>
77         </Border>
78         <Frame Grid.Column="1">
79             <Frame.Background>
80                 <VisualBrush Stretch="Uniform" Opacity="0.5" Viewbox="-1,-1,3,3">
81                     <VisualBrush.Visual>
82                         <TextBlock Text="BigBox777"/>
83                     </VisualBrush.Visual>
84                 </VisualBrush>
85             </Frame.Background>
86         </Frame>
87     </Grid>
88 </Page>
PSystemView.xaml

③模組 Demo10A-Framework 資料夾 ViewModels 下建立系統頁的ViewModel,PSystemViewModel.cs。

 1 using Demo10A_Framework.Core;
 2 using Demo10A_Framework.Globals;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8 
 9 namespace Demo10A_Framework.ViewModels
10 {
11     public class PSystemViewModel:BaseViewModel
12     {
13         #region 事件-訊息框 + public DelegateCommand CallMessageBoxCommand
14         public DelegateCommand CallMessageBoxCommand
15         {
16             get
17             {
18                 return new DelegateCommand(CallMessageBoxCommand_Executed);
19             }
20         }
21 
22         private void CallMessageBoxCommand_Executed(object obj)
23         {
24             MessageBox("快捷支付多份心,莫名中獎少頓惜。 網購陷阱花樣多,線上交易要當心。", "防詐提醒");
25         }
26         #endregion
27 
28         #region 屬性-系統標題 + public string SystemTitle
29         private string _systemTitle = "系統視窗";
30         public string SystemTitle
31         {
32             get { return _systemTitle; }
33             set
34             {
35                 _systemTitle = value;
36                 RaisePropertyChanged();
37             }
38         }
39         #endregion
40 
41         #region 事件-更改標題 + public DelegateCommand ChangeWindowTitleCommand
42         public DelegateCommand ChangeWindowTitleCommand
43         {
44             get
45             {
46                 return new DelegateCommand(ChangeWindowTitleCommand_Executed);
47             }
48         }
49 
50         private void ChangeWindowTitleCommand_Executed(object obj)
51         {
52             GlobalVisualizedData.SetMainWindowTitle(SystemTitle);
53         }
54         #endregion
55 
56         #region 屬性-圓狀態 + public bool EllipseState
57         private bool _ellipseState;
58 
59         public bool EllipseState
60         {
61             get { return _ellipseState; }
62             set
63             {
64                 _ellipseState = value;
65                 RaisePropertyChanged();
66             }
67         } 
68         #endregion
69 
70 
71         #region 事件-轉換器使用 + public DelegateCommand UseConverterCommand
72         public DelegateCommand UseConverterCommand
73         {
74             get
75             {
76                 return new DelegateCommand(UseConverterCommand_Executed);
77             }
78         }
79 
80         private void UseConverterCommand_Executed(object obj)
81         {
82             EllipseState = !EllipseState;
83         }
84         #endregion
85 
86         #region 建構函式 + public PSystemViewModel()
87         public PSystemViewModel()
88         {
89             GlobalVisualizedData.SetMainWindowTitle("系統主頁[BigBox777]");
90         } 
91         #endregion
92     }
93 }
PSystemViewModel.cs

④以上就完成了轉換器和帶引數的轉換器案例。

 

3.4、新增日誌頁

  這節我們把系統頁面上的導航用起來,在第一個頁面裡面放一個textBox,放一些日誌,並實現假資料的查詢。

①模組 Demo10A-Framework 資料夾 ViewModels 下建立日誌頁的ViewModel,PLoggerViewModel.cs。

 1 using Demo10A_Framework.Core;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace Demo10A_Framework.ViewModels
 9 {
10     public class PLoggerViewModel:BaseViewModel
11     {
12         #region 屬性-日誌內容 + public string LogContent
13         private string _logContent;
14 
15         public string LogContent
16         {
17             get { return _logContent; }
18             set
19             {
20                 _logContent = value;
21                 RaisePropertyChanged();
22             }
23         }
24         #endregion
25 
26         private StringBuilder _stringBuilder = new StringBuilder();
27         #region 建構函式 + public PLoggerViewModel()
28         public PLoggerViewModel()
29         {
30 
31         }
32         #endregion
33 
34         #region 寫日誌 + public void WriteLog(Type type,string content)
35         public void WriteLog(Type type,string content)
36         {
37             _stringBuilder.AppendLine(string.Format("{0}[{1}]: {2}", type.FullName, DateTime.UtcNow, content));
38             LogContent = _stringBuilder.ToString();
39         } 
40         #endregion
41     }
42 }
PLoggerViewModel.cs

②模組 Demo10A-Framework 資料夾 Views 下建立日誌頁的View,PLoggerView.xaml。

 1 <Page x:Class="Demo10A_Framework.Views.PLoggerView"
 2       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5       xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6       xmlns:local="clr-namespace:Demo10A_Framework.Views"
 7       mc:Ignorable="d" 
 8       d:DesignHeight="450" d:DesignWidth="800"
 9       Title="PLoggerView">
10 
11     <Grid>
12         <TextBox Text="{Binding LogContent}" Margin="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"/>
13     </Grid>
14 </Page>
PLoggerView.xaml

③模組 Demo10A-Framework 資料夾 Globals 下更新GlobalVisualizedData.cs,加入初始化日誌頁程式碼和寫日誌方法。

 1 using Demo10A_Framework.ViewModels;
 2 using Demo10A_Framework.Views;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading;
 8 using System.Threading.Tasks;
 9 using System.Windows;
10 
11 namespace Demo10A_Framework.Globals
12 {
13     public class GlobalVisualizedData
14     {
15         #region 常量-Views配置資訊
16         private const string _viewsAssemblyName = "Demo10A-Framework";
17         private const string _viewsNamespace = "Demo10A_Framework.Views";
18         #endregion
19         #region 全域性-ViewModel資訊
20         private static WMainViewModel _mainViewModel; //全域性主視窗ViewModel
21         private static PSystemViewModel _systemViewModel; //全域性系統頁ViewModel 
22         private static PLoggerViewModel _loggerViewModel; //全域性Logger頁ViewModel 
23         #endregion
24 
25         #region 使用歡迎頁 + public static void UseWelcomeWindow(bool isUseWelcomeWindow, int delayMilliseconds)
26         public static void UseWelcomeWindow(bool isUseWelcomeWindow, int delayMilliseconds)
27         {
28             if (isUseWelcomeWindow)
29             {
30                 _mainViewModel = new WMainViewModel(_viewsAssemblyName, _viewsNamespace);
31                 var welcome = new WWelcomeViewModel();
32                 welcome.Show();
33                 App.Current.Dispatcher.Invoke(() =>
34                 {  //跨執行緒操作UI
35                     Task.WaitAll(Task.Delay(delayMilliseconds));
36                     welcome.Close();
37                     ShowMainView();
38                 });
39             }
40             else
41             {
42                 _mainViewModel = new WMainViewModel(_viewsAssemblyName, _viewsNamespace);
43                 ShowMainView();
44             }
45 
46         }
47         private static void ShowMainView()
48         {
49             _mainViewModel.Show();
50             _systemViewModel = new PSystemViewModel();
51             _mainViewModel.MainFrameNavigation(_systemViewModel.UIElement as PSystemView);
52             _loggerViewModel = new PLoggerViewModel();
53             _systemViewModel.SystemFrameNavigation(_loggerViewModel.UIElement as PLoggerView);
54         }
55         #endregion
56 
57         #region 設定主窗體標題 + public static void SetMainWindowTitle(string title)
58         public static void SetMainWindowTitle(string title)
59         {
60             _mainViewModel.WindowTitle = title;
61         }
62         #endregion
63 
64         #region 寫日誌 + public static void WriteLog(Type type,string content)
65         public static void WriteLog(Type type, string content)
66         {
67             _loggerViewModel.WriteLog(type,content);
68         }
69         #endregion
70     }
71 }
GlobalVisualizedData.cs

④模組 Demo10A-Framework 資料夾 ViewModels 下更新系統頁的ViewModel,PSystemViewModel.cs對操作動作記錄到日誌。

  1 using Demo10A_Framework.Core;
  2 using Demo10A_Framework.Globals;
  3 using Demo10A_Framework.Views;
  4 using System;
  5 using System.Collections.Generic;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Threading.Tasks;
  9 using System.Windows;
 10 
 11 namespace Demo10A_Framework.ViewModels
 12 {
 13     public class PSystemViewModel:BaseViewModel
 14     {
 15         #region 事件-訊息框 + public DelegateCommand CallMessageBoxCommand
 16         public DelegateCommand CallMessageBoxCommand
 17         {
 18             get
 19             {
 20                 return new DelegateCommand(CallMessageBoxCommand_Executed);
 21             }
 22         }
 23 
 24         private void CallMessageBoxCommand_Executed(object obj)
 25         {
 26             GlobalVisualizedData.WriteLog(typeof(PSystemViewModel), string.Format("建立訊息提示框,訊息標題:{0},訊息:{1}", "防詐提醒", "快捷支付多份心,莫名中獎少頓惜。 網購陷阱花樣多,線上交易要當心。"));
 27             MessageBox("快捷支付多份心,莫名中獎少頓惜。 網購陷阱花樣多,線上交易要當心。", "防詐提醒");
 28         }
 29         #endregion
 30 
 31         #region 屬性-系統標題 + public string SystemTitle
 32         private string _systemTitle = "系統視窗";
 33         public string SystemTitle
 34         {
 35             get { return _systemTitle; }
 36             set
 37             {
 38                 _systemTitle = value;
 39                 RaisePropertyChanged();
 40             }
 41         }
 42         #endregion
 43 
 44         #region 事件-更改標題 + public DelegateCommand ChangeWindowTitleCommand
 45         public DelegateCommand ChangeWindowTitleCommand
 46         {
 47             get
 48             {
 49                 return new DelegateCommand(ChangeWindowTitleCommand_Executed);
 50             }
 51         }
 52 
 53         private void ChangeWindowTitleCommand_Executed(object obj)
 54         {
 55             GlobalVisualizedData.WriteLog(typeof(PSystemViewModel), string.Format("更改主視窗標題,SystemTitle={0}", SystemTitle));
 56             GlobalVisualizedData.SetMainWindowTitle(SystemTitle);
 57         }
 58         #endregion
 59 
 60         #region 屬性-圓狀態 + public bool EllipseState
 61         private bool _ellipseState;
 62 
 63         public bool EllipseState
 64         {
 65             get { return _ellipseState; }
 66             set
 67             {
 68                 _ellipseState = value;
 69                 RaisePropertyChanged();
 70             }
 71         } 
 72         #endregion
 73 
 74         #region 事件-轉換器使用 + public DelegateCommand UseConverterCommand
 75         public DelegateCommand UseConverterCommand
 76         {
 77             get
 78             {
 79                 return new DelegateCommand(UseConverterCommand_Executed);
 80             }
 81         }
 82 
 83         private void UseConverterCommand_Executed(object obj)
 84         {
 85             GlobalVisualizedData.WriteLog(typeof(PSystemViewModel), string.Format("使用轉換器更改圓狀態,EllipseState={0}", EllipseState));
 86             EllipseState = !EllipseState;
 87         }
 88         #endregion
 89 
 90         #region 建構函式 + public PSystemViewModel()
 91         public PSystemViewModel()
 92         {
 93             GlobalVisualizedData.SetMainWindowTitle("系統主頁[BigBox777]");
 94         }
 95         #endregion
 96 
 97         #region 系統Frame導航 + public void SystemFrameNavigation(FrameworkElement element)
 98         public void SystemFrameNavigation(FrameworkElement element)
 99         {
100             (UIElement as PSystemView).systemFrame.Navigate(element);
101         }
102         #endregion
103     }
104 }
PSystemViewModel.cs

⑤完成上面步驟已經完成了新增日誌頁功能。


3.5、模型業務呼叫

  這節來做一個模型裡面業務使用者登入的案例。

①模組 Demo10A-Framework 資料夾 Views 下更新系統頁的View,新增登入介面。

 1 <Page x:Class="Demo10A_Framework.Views.PSystemView"
 2       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5       xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6       xmlns:local="clr-namespace:Demo10A_Framework.Views" xmlns:converters="clr-namespace:Demo10A_Framework.Converters"
 7       mc:Ignorable="d" 
 8       d:DesignHeight="450" d:DesignWidth="800"
 9       Title="PSystemView">
10     <Page.Resources>
11         <converters:ConvertChangeState2EllipseFill x:Key="changeStateConvert"/>
12     </Page.Resources>
13     <Grid>
14         <Grid.ColumnDefinitions>
15             <ColumnDefinition Width="250"/>
16             <ColumnDefinition/>
17         </Grid.ColumnDefinitions>
18         <Border Margin="1,0,0,1" Grid.Column="0" BorderThickness="1,1,1,1" BorderBrush="Black">
19             <StackPanel>
20                 <Button Height="30" Content="彈出訊息框" Command="{Binding CallMessageBoxCommand}"/>
21                 <Border Margin="0" Padding="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="Red">
22                     <Grid Height="60">
23                         <Grid.ColumnDefinitions>
24                             <ColumnDefinition Width="60"/>
25                             <ColumnDefinition/>
26                         </Grid.ColumnDefinitions>
27                         <Grid.RowDefinitions>
28                             <RowDefinition/>
29                             <RowDefinition/>
30                         </Grid.RowDefinitions>
31                         <TextBlock Text="視窗標題:" VerticalAlignment="Center"/>
32                         <TextBox Text="{Binding SystemTitle}" Grid.Column="1" VerticalAlignment="Center"/>
33                         <Button Content="改變視窗標題" Command="{Binding ChangeWindowTitleCommand}" Grid.Row="1" Grid.ColumnSpan="2"/>
34                     </Grid>
35                 </Border>
36                 <Border Margin="0" Padding="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="Red">
37                     <Grid Height="60">
38                         <Grid.RowDefinitions>
39                             <RowDefinition/>
40                             <RowDefinition/>
41                         </Grid.RowDefinitions>
42                         <StackPanel Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal">
43                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert}}" Margin="0,0,5,0"/>
44                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert}}" Margin="0,0,5,0"/>
45                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='1'}" Margin="0,0,5,0"/>
46                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='1'}" Margin="0,0,5,0"/>
47                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='2'}" Margin="0,0,5,0"/>
48                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='2'}" Margin="0,0,5,0"/>
49                         </StackPanel>
50                         <Button Content="轉換器使用" Command="{Binding UseConverterCommand}" Grid.Row="1" Grid.ColumnSpan="2"/>
51                     </Grid>
52                 </Border>
53                 <Button Height="30" Content="建立新視窗"/>
54                 <Button Height="30" Content="關閉新視窗"/>
55                 <Border Margin="0" Padding="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="Red">
56                     <Grid Height="80">
57                         <Grid.ColumnDefinitions>
58                             <ColumnDefinition Width="60"/>
59                             <ColumnDefinition/>
60                         </Grid.ColumnDefinitions>
61                         <Grid.RowDefinitions>
62                             <RowDefinition/>
63                             <RowDefinition/>
64                             <RowDefinition/>
65                         </Grid.RowDefinitions>
66 
67                         <TextBlock Text="使用者名稱:" VerticalAlignment="Center"/>
68                         <TextBox Text="{Binding UserName}" Grid.Column="1" VerticalAlignment="Center"/>
69                         <TextBlock Text="密碼:" Grid.Row="1" VerticalAlignment="Center"/>
70                         <TextBox Text="{Binding PWD}" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center"/>
71                         <Button Content="登入" Command="{Binding LoginCommand}" Grid.Row="2" Grid.ColumnSpan="2"/>
72                     </Grid>
73                 </Border>
74                 <Button Height="30" Content="切換頁面"/>
75                 <Button Height="30" Content="分頁顯示"/>
76             </StackPanel>
77         </Border>
78         <Frame x:Name="systemFrame" Grid.Column="1">
79             <Frame.Background>
80                 <VisualBrush Stretch="Uniform" Opacity="0.5" Viewbox="-1,-1,3,3">
81                     <VisualBrush.Visual>
82                         <TextBlock Text="BigBox777"/>
83                     </VisualBrush.Visual>
84                 </VisualBrush>
85             </Frame.Background>
86         </Frame>
87     </Grid>
88 </Page>
PSystemView.xaml

②模組 Demo10A-Framework 資料夾 ViewModels 下更新系統頁的ViewModel,新增登入的命令和屬性繫結。

  1 using Demo10A_Framework.Core;
  2 using Demo10A_Framework.Globals;
  3 using Demo10A_Framework.Views;
  4 using Demo10A_Models;
  5 using System;
  6 using System.Collections.Generic;
  7 using System.Linq;
  8 using System.Text;
  9 using System.Threading.Tasks;
 10 using System.Windows;
 11 
 12 namespace Demo10A_Framework.ViewModels
 13 {
 14     public class PSystemViewModel:BaseViewModel
 15     {
 16         #region 事件-訊息框 + public DelegateCommand CallMessageBoxCommand
 17         public DelegateCommand CallMessageBoxCommand
 18         {
 19             get
 20             {
 21                 return new DelegateCommand(CallMessageBoxCommand_Executed);
 22             }
 23         }
 24 
 25         private void CallMessageBoxCommand_Executed(object obj)
 26         {
 27             GlobalVisualizedData.WriteLog(typeof(PSystemViewModel), string.Format("建立訊息提示框,訊息標題:{0},訊息:{1}", "防詐提醒", "快捷支付多份心,莫名中獎少頓惜。 網購陷阱花樣多,線上交易要當心。"));
 28             MessageBox("快捷支付多份心,莫名中獎少頓惜。 網購陷阱花樣多,線上交易要當心。", "防詐提醒");
 29         }
 30         #endregion
 31 
 32         #region 屬性-系統標題 + public string SystemTitle
 33         private string _systemTitle = "系統視窗";
 34         public string SystemTitle
 35         {
 36             get { return _systemTitle; }
 37             set
 38             {
 39                 _systemTitle = value;
 40                 RaisePropertyChanged();
 41             }
 42         }
 43         #endregion
 44 
 45         #region 事件-更改標題 + public DelegateCommand ChangeWindowTitleCommand
 46         public DelegateCommand ChangeWindowTitleCommand
 47         {
 48             get
 49             {
 50                 return new DelegateCommand(ChangeWindowTitleCommand_Executed);
 51             }
 52         }
 53 
 54         private void ChangeWindowTitleCommand_Executed(object obj)
 55         {
 56             GlobalVisualizedData.WriteLog(typeof(PSystemViewModel), string.Format("更改主視窗標題,SystemTitle={0}", SystemTitle));
 57             GlobalVisualizedData.SetMainWindowTitle(SystemTitle);
 58         }
 59         #endregion
 60 
 61         #region 屬性-圓狀態 + public bool EllipseState
 62         private bool _ellipseState;
 63 
 64         public bool EllipseState
 65         {
 66             get { return _ellipseState; }
 67             set
 68             {
 69                 _ellipseState = value;
 70                 RaisePropertyChanged();
 71             }
 72         } 
 73         #endregion
 74 
 75         #region 事件-轉換器使用 + public DelegateCommand UseConverterCommand
 76         public DelegateCommand UseConverterCommand
 77         {
 78             get
 79             {
 80                 return new DelegateCommand(UseConverterCommand_Executed);
 81             }
 82         }
 83 
 84         private void UseConverterCommand_Executed(object obj)
 85         {
 86             GlobalVisualizedData.WriteLog(typeof(PSystemViewModel), string.Format("使用轉換器更改圓狀態,EllipseState={0}", EllipseState));
 87             EllipseState = !EllipseState;
 88         }
 89         #endregion
 90 
 91         #region 屬性-使用者名稱 + public string UserName
 92         private string _userName = "BigBox777";
 93         public string UserName
 94         {
 95             get { return _userName; }
 96             set
 97             {
 98                 _userName = value;
 99                 RaisePropertyChanged();
100             }
101         }
102         #endregion
103 
104         #region 屬性-密碼 + public string PWD
105         private string _PWD = "12345";
106         public string PWD
107         {
108             get { return _PWD; }
109             set
110             {
111                 _PWD = value;
112                 RaisePropertyChanged();
113             }
114         }
115         #endregion
116 
117         #region 事件-登入 + public DelegateCommand LoginCommand
118         public DelegateCommand LoginCommand
119         {
120             get
121             {
122                 return new DelegateCommand(LoginCommand_Executed);
123             }
124         }
125 
126         private void LoginCommand_Executed(object obj)
127         {
128             
129             var result = UserInfo.Login(UserName,PWD);
130             GlobalVisualizedData.WriteLog(typeof(PSystemViewModel), string.Format("UserName={0},Password={1},[{2}]", EllipseState, PWD, result.Message));
131             MessageBox(result.Message);
132         }
133         #endregion
134 
135 
136         #region 建構函式 + public PSystemViewModel()
137         public PSystemViewModel()
138         {
139             GlobalVisualizedData.SetMainWindowTitle("系統主頁[BigBox777]");
140         }
141         #endregion
142 
143         #region 系統Frame導航 + public void SystemFrameNavigation(FrameworkElement element)
144         public void SystemFrameNavigation(FrameworkElement element)
145         {
146             (UIElement as PSystemView).systemFrame.Navigate(element);
147         }
148         #endregion
149     }
150 }
PSystemViewModel.cs

③模組 Demo10A-Models 下新增UserInfo的Login邏輯及返回值LoginResult定義。

 1 using Demo10A_Infrastructure.DTO;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace Demo10A_Models
 9 {
10     public class LoginResult
11     {
12         public bool Success { get; set; }
13         public string Message { get; set; }
14         public TableUserInfo User { get; set; }
15     }
16 }
LoginResult.cs
 1 using Demo10A_Infrastructure.DTO;
 2 using Demo10A_Infrastructure.Utility;
 3 using System;
 4 using System.Text.Json;
 5 
 6 namespace Demo10A_Models
 7 {
 8     public class UserInfo
 9     {
10         public static LoginResult Login(string userName,string password)
11         {
12             var tUser= DBHelper.QueryByUsername(userName);
13             if (tUser.Password.Equals(password))
14             {
15                 
16                 return new LoginResult { Success=true,Message=string.Format("登入成功:{0}", JsonSerializer.Serialize(tUser)),User= tUser };
17             }
18             return new LoginResult { Success = false, Message = "密碼不匹配" };
19         }
20     }
21 }
UserInfo.cs

④模組 Demo10A-Infrastructure 資料夾 DTO 下建立資料庫表物件TableUserInfo。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace Demo10A_Infrastructure.DTO
 8 {
 9     public class TableUserInfo
10     {
11         public int Id { get; set; }
12         public string UserName { get; set; }
13         public string Password { get; set; }
14         public int Age { get; set; }
15         public decimal Income { get; set; }//收入
16         public string Hobby { get; set; } //愛好
17     }
18 }
TableUserInfo.cs

⑤模組 Demo10A-Infrastructure 資料夾 Utility 下建立假資料訪問幫助檔案DBHelper。

 1 using Demo10A_Infrastructure.DTO;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace Demo10A_Infrastructure.Utility
 9 {
10     public class DBHelper
11     {
12         private static List<TableUserInfo> userInfos = new List<TableUserInfo>();
13         static DBHelper()
14         {
15             userInfos.Add(new TableUserInfo { Id = 1, UserName = "BiBo1", Password = "1", Age = 41, Income = 20m, Hobby = "足球" });
16             userInfos.Add(new TableUserInfo { Id = 1, UserName = "BiBo2", Password = "1", Age = 52, Income = 20m, Hobby = "足球" });
17             userInfos.Add(new TableUserInfo { Id = 1, UserName = "BiBo3", Password = "1", Age = 26, Income = 20m, Hobby = "足球" });
18             userInfos.Add(new TableUserInfo { Id = 1, UserName = "BiBo4", Password = "1", Age = 96, Income = 20m, Hobby = "足球" });
19             userInfos.Add(new TableUserInfo { Id = 1, UserName = "BiBo5", Password = "1", Age = 18, Income = 20m, Hobby = "足球" });
20             userInfos.Add(new TableUserInfo { Id = 1, UserName = "BiBo6", Password = "1", Age = 60, Income = 20m, Hobby = "足球" });
21             userInfos.Add(new TableUserInfo { Id = 1, UserName = "BiBo7", Password = "1", Age = 92, Income = 20m, Hobby = "足球" });
22             userInfos.Add(new TableUserInfo { Id = 1, UserName = "BiBo8", Password = "1", Age = 49, Income = 20m, Hobby = "足球" });
23             userInfos.Add(new TableUserInfo { Id = 1, UserName = "BiBo9", Password = "1", Age = 22, Income = 20m, Hobby = "足球" });
24             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Mike1", Password = "1", Age = 77, Income = 20m, Hobby = "足球" });
25             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Mike2", Password = "1", Age = 10, Income = 20m, Hobby = "足球" });
26             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Mike3", Password = "1", Age = 27, Income = 20m, Hobby = "足球" });
27             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Mike4", Password = "1", Age = 29, Income = 20m, Hobby = "足球" });
28             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Mike5", Password = "1", Age = 81, Income = 20m, Hobby = "足球" });
29             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Mike6", Password = "1", Age = 90, Income = 20m, Hobby = "足球" });
30             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Mike7", Password = "1", Age = 98, Income = 20m, Hobby = "足球" });
31             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Mike8", Password = "1", Age = 42, Income = 20m, Hobby = "足球" });
32             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Mike9", Password = "1", Age = 40, Income = 20m, Hobby = "足球" });
33             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anie1", Password = "1", Age = 48, Income = 20m, Hobby = "足球" });
34             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anie2", Password = "1", Age = 74, Income = 20m, Hobby = "足球" });
35             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anie3", Password = "1", Age = 69, Income = 20m, Hobby = "足球" });
36             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anie4", Password = "1", Age = 82, Income = 20m, Hobby = "足球" });
37             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anie5", Password = "1", Age = 85, Income = 20m, Hobby = "足球" });
38             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anie6", Password = "1", Age = 40, Income = 20m, Hobby = "足球" });
39             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anie7", Password = "1", Age = 59, Income = 20m, Hobby = "足球" });
40             userInfos.Add(new TableUserInfo { Id = 1, UserName = "BigBox777", Password = "12345", Age = 18, Income = 20m, Hobby = "足球" });
41             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anie8", Password = "1", Age = 38, Income = 20m, Hobby = "足球" });
42             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anie9", Password = "1", Age = 72, Income = 20m, Hobby = "足球" });
43             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Tomas1", Password = "1", Age = 75, Income = 20m, Hobby = "足球" });
44             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Tomas2", Password = "1", Age = 68, Income = 20m, Hobby = "足球" });
45             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Tomas3", Password = "1", Age = 69, Income = 20m, Hobby = "足球" });
46             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Tomas4", Password = "1", Age = 73, Income = 20m, Hobby = "足球" });
47             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Tomas5", Password = "1", Age = 38, Income = 20m, Hobby = "足球" });
48             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Tomas6", Password = "1", Age = 20, Income = 20m, Hobby = "足球" });
49             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Tomas7", Password = "1", Age = 28, Income = 20m, Hobby = "足球" });
50             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Tomas8", Password = "1", Age = 31, Income = 20m, Hobby = "足球" });
51             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Tomas9", Password = "1", Age = 7, Income = 20m, Hobby = "足球" });
52             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anti1", Password = "1", Age = 99, Income = 20m, Hobby = "足球" });
53             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anti2", Password = "1", Age = 2, Income = 20m, Hobby = "足球" });
54             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anti3", Password = "1", Age = 10, Income = 20m, Hobby = "足球" });
55             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anti4", Password = "1", Age = 53, Income = 20m, Hobby = "足球" });
56             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anti5", Password = "1", Age = 55, Income = 20m, Hobby = "足球" });
57             userInfos.Add(new TableUserInfo { Id = 1, UserName = "Anti6", Password = "1", Age = 34, Income = 20m, Hobby = "足球" });
58         }
59         public static List<TableUserInfo> QueryAllUserInfo()
60         {
61             return userInfos;
62         }
63         public static TableUserInfo QueryByUsername(string userName)
64         {
65             return userInfos.FirstOrDefault<TableUserInfo>(u => u.UserName.Equals(userName));
66         }
67     }
68 }
DBHelper.cs

⑥以上就完成了一個基本的模型業務的使用過程。

 

3.6、切換可視頁面

  SPA應用中很多時候需要區域性切換視覺化區域,我們來做個切換視覺化區域的案例。

①模組 Demo10A-Framework 資料夾 ViewModels 下新增資料區域的ViewModel。

 1 using Demo10A_Framework.Core;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace Demo10A_Framework.ViewModels
 9 {
10     public class PDatagridViewModel:BaseViewModel
11     {
12     }
13 }
PDatagridViewModel.cs

②模組 Demo10A-Framework 資料夾 Views 下新增資料區域的View。

 1 <Page x:Class="Demo10A_Framework.Views.PDatagridView"
 2       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5       xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6       xmlns:local="clr-namespace:Demo10A_Framework.Views"
 7       mc:Ignorable="d" 
 8       d:DesignHeight="450" d:DesignWidth="800"
 9       Title="PDatagridView">
10     <Grid>
11         
12     </Grid>
13 </Page>
PDatagridView.xaml

③模組 Demo10A-Framework 資料夾 Views 下更新系統頁的View,新增切換頁面按鈕。

 1 <Page x:Class="Demo10A_Framework.Views.PSystemView"
 2       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5       xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6       xmlns:local="clr-namespace:Demo10A_Framework.Views" xmlns:converters="clr-namespace:Demo10A_Framework.Converters"
 7       mc:Ignorable="d" 
 8       d:DesignHeight="450" d:DesignWidth="800"
 9       Title="PSystemView">
10     <Page.Resources>
11         <converters:ConvertChangeState2EllipseFill x:Key="changeStateConvert"/>
12     </Page.Resources>
13     <Grid>
14         <Grid.ColumnDefinitions>
15             <ColumnDefinition Width="250"/>
16             <ColumnDefinition/>
17         </Grid.ColumnDefinitions>
18         <Border Margin="1,0,0,1" Grid.Column="0" BorderThickness="1,1,1,1" BorderBrush="Black">
19             <StackPanel>
20                 <Button Height="30" Content="彈出訊息框" Command="{Binding CallMessageBoxCommand}"/>
21                 <Border Margin="0" Padding="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="Red">
22                     <Grid Height="60">
23                         <Grid.ColumnDefinitions>
24                             <ColumnDefinition Width="60"/>
25                             <ColumnDefinition/>
26                         </Grid.ColumnDefinitions>
27                         <Grid.RowDefinitions>
28                             <RowDefinition/>
29                             <RowDefinition/>
30                         </Grid.RowDefinitions>
31                         <TextBlock Text="視窗標題:" VerticalAlignment="Center"/>
32                         <TextBox Text="{Binding SystemTitle}" Grid.Column="1" VerticalAlignment="Center"/>
33                         <Button Content="改變視窗標題" Command="{Binding ChangeWindowTitleCommand}" Grid.Row="1" Grid.ColumnSpan="2"/>
34                     </Grid>
35                 </Border>
36                 <Border Margin="0" Padding="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="Red">
37                     <Grid Height="60">
38                         <Grid.RowDefinitions>
39                             <RowDefinition/>
40                             <RowDefinition/>
41                         </Grid.RowDefinitions>
42                         <StackPanel Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal">
43                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert}}" Margin="0,0,5,0"/>
44                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert}}" Margin="0,0,5,0"/>
45                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='1'}" Margin="0,0,5,0"/>
46                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='1'}" Margin="0,0,5,0"/>
47                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='2'}" Margin="0,0,5,0"/>
48                             <Ellipse Width="28" Height="28" Fill="{Binding EllipseState,Converter={StaticResource changeStateConvert},ConverterParameter='2'}" Margin="0,0,5,0"/>
49                         </StackPanel>
50                         <Button Content="轉換器使用" Command="{Binding UseConverterCommand}" Grid.Row="1" Grid.ColumnSpan="2"/>
51                     </Grid>
52                 </Border>
53                 <Button Height="30" Content="建立新視窗"/>
54                 <Button Height="30" Content="關閉新視窗"/>
55                 <Border Margin="0" Padding="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="Red">
56                     <Grid Height="80">
57                         <Grid.ColumnDefinitions>
58                             <ColumnDefinition Width="60"/>
59                             <ColumnDefinition/>
60                         </Grid.ColumnDefinitions>
61                         <Grid.RowDefinitions>
62                             <RowDefinition/>
63                             <RowDefinition/>
64                             <RowDefinition/>
65                         </Grid.RowDefinitions>
66                         <TextBlock Text="使用者名稱:" VerticalAlignment="Center"/>
67                         <TextBox Text="{Binding UserName}" Grid.Column="1" VerticalAlignment="Center"/>
68                         <TextBlock Text="密碼:" Grid.Row="1" VerticalAlignment="Center"/>
69                         <TextBox Text="{Binding PWD}" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center"/>
70                         <Button Content="登入" Command="{Binding LoginCommand}" Grid.Row="2" Grid.ColumnSpan="2"/>
71                     </Grid>
72                 </Border>
73                 <Button Height="30" Content="切換頁面" Command="{Binding CreateDataPageCommand}"/>
74                 <Button Height="30" Content="查詢結果分頁顯示" Command="{Binding QueryPaginationCommand}"/>
75             </StackPanel>
76         </Border>
77         <Frame x:Name="systemFrame" Grid.Column="1">
78             <Frame.Background>
79                 <VisualBrush Stretch="Uniform" Opacity="0.5" Viewbox="-1,-1,3,3">
80                     <VisualBrush.Visual>
81                         <TextBlock Text="BigBox777"/>
82                     </VisualBrush.Visual>
83                 </VisualBrush>
84             </Frame.Background>
85         </Frame>
86     </Grid>
87 </Page>
PSystemView.xaml

④模組 Demo10A-Framework 資料夾 ViewModels 下更新系統頁的ViewModel,新增切換命令。

  1 using Demo10A_Framework.Core;
  2 using Demo10A_Framework.Globals;
  3 using Demo10A_Framework.Views;
  4 using Demo10A_Models;
  5 using System;
  6 using System.Collections.Generic;
  7 using System.Linq;
  8 using System.Text;
  9 using System.Threading.Tasks;
 10 using System.Windows;
 11 using System.Windows.Controls;
 12 
 13 namespace Demo10A_Framework.ViewModels
 14 {
 15     public class PSystemViewModel:BaseViewModel
 16     {
 17         #region 事件-訊息框 + public DelegateCommand CallMessageBoxCommand
 18         public DelegateCommand CallMessageBoxCommand
 19         {
 20             get
 21             {
 22                 return new DelegateCommand(CallMessageBoxCommand_Executed);
 23             }
 24         }
 25 
 26         private void CallMessageBoxCommand_Executed(object obj)
 27         {
 28             GlobalVisualizedData.WriteLog(typeof(PSystemViewModel), string.Format("建立訊息提示框,訊息標題:{0},訊息:{1}", "防詐提醒", "快捷支付多份心,莫名中獎少頓惜。 網購陷阱花樣多,線上交易要當心。"));
 29             MessageBox("快捷支付多份心,莫名中獎少頓惜。 網購陷阱花樣多,線上交易要當心。", "防詐提醒");
 30         }
 31         #endregion
 32 
 33         #region 屬性-系統標題 + public string SystemTitle
 34         private string _systemTitle = "系統主頁[BigBox777]";
 35         public string SystemTitle
 36         {
 37             get { return _systemTitle; }
 38             set
 39             {
 40                 _systemTitle = value;
 41                 RaisePropertyChanged();
 42             }
 43         }
 44         #endregion
 45 
 46         #region 事件-更改標題 + public DelegateCommand ChangeWindowTitleCommand
 47         public DelegateCommand ChangeWindowTitleCommand
 48         {
 49             get
 50             {
 51                 return new DelegateCommand(ChangeWindowTitleCommand_Executed);
 52             }
 53         }
 54 
 55         private void ChangeWindowTitleCommand_Executed(object obj)
 56         {
 57             GlobalVisualizedData.WriteLog(typeof(PSystemViewModel), string.Format("更改主視窗標題,SystemTitle={0}", SystemTitle));
 58             GlobalVisualizedData.SetMainWindowTitle(SystemTitle);
 59         }
 60         #endregion
 61 
 62         #region 屬性-圓狀態 + public bool EllipseState
 63         private bool _ellipseState;
 64 
 65         public bool EllipseState
 66         {
 67             get { return _ellipseState; }
 68             set
 69             {
 70                 _ellipseState = value;
 71                 RaisePropertyChanged();
 72             }
 73         } 
 74         #endregion
 75 
 76         #region 事件-轉換器使用 + public DelegateCommand UseConverterCommand
 77         public DelegateCommand UseConverterCommand
 78         {
 79             get
 80             {
 81                 return new DelegateCommand(UseConverterCommand_Executed);
 82             }
 83         }
 84 
 85         private void UseConverterCommand_Executed(object obj)
 86         {
 87             GlobalVisualizedData.WriteLog(typeof(PSystemViewModel), string.Format("使用轉換器更改圓狀態,EllipseState={0}", EllipseState));
 88             EllipseState = !EllipseState;
 89         }
 90         #endregion
 91 
 92         #region 屬性-使用者名稱 + public string UserName
 93         private string _userName = "BigBox777";
 94         public string UserName
 95         {
 96             get { return _userName; }
 97             set
 98             {
 99                 _userName = value;
100                 RaisePropertyChanged();
101             }
102         }
103         #endregion
104 
105         #region 屬性-密碼 + public string PWD
106         private string _PWD = "12345";
107         public string PWD
108         {
109             get { return _PWD; }
110             set
111             {
112                 _PWD = value;
113                 RaisePropertyChanged();
114             }
115         }
116         #endregion
117 
118         #region 事件-登入 + public DelegateCommand LoginCommand
119         public DelegateCommand LoginCommand
120         {
121             get
122             {
123                 return new DelegateCommand(LoginCommand_Executed);
124             }
125         }
126 
127         private void LoginCommand_Executed(object obj)
128         {
129             UserInfo userInfo = new UserInfo();
130             var result = userInfo.Login(UserName,PWD);
131             GlobalVisualizedData.WriteLog(typeof(PSystemViewModel), string.Format("UserName={0},Password={1},[{2}]", EllipseState, PWD, result.Message));
132             MessageBox(result.Message);
133         }
134         #endregion
135 
136         #region 事件-切換頁 + public DelegateCommand CreateDataPageCommand
137         public DelegateCommand CreateDataPageCommand
138         {
139             get
140             {
141                 return new DelegateCommand(CreateDataPageCommand_Executed);
142             }
143         }
144 
145         private void CreateDataPageCommand_Executed(object obj)
146         {
147             var frame = (UIElement as PSystemView).systemFrame;
148             if (frame.Content is PLoggerView)
149             {
150                 (UIElement as PSystemView).systemFrame.Navigate(datagridViewModel.UIElement);
151             }
152             else
153             {
154                 (UIElement as PSystemView).systemFrame.Navigate(loggerViewModel.UIElement);
155             }
156         }
157         #endregion
158 
159 
160         internal PLoggerViewModel loggerViewModel; //Logger頁ViewModel 
161         internal PDatagridViewModel datagridViewModel; //Datagrid頁ViewModel
162 
163         #region 建構函式 + public PSystemViewModel()
164         public PSystemViewModel()
165         {
166             loggerViewModel = new PLoggerViewModel();
167             datagridViewModel = new PDatagridViewModel();
168             (UIElement as PSystemView).systemFrame.Navigate(loggerViewModel.UIElement);
169         }
170         #endregion        
171     }
172 }
PSystemViewModel.cs

⑤以上就完成了視覺化區域的切換,右側區域可以在日誌顯示和資料顯示間來回切換。


3.7、查詢資料分頁顯示

  常見查詢回來的資料集合都非常的大,這節我們來做個分頁顯示的案例。

①模組 Demo10A-Framework 資料夾 ViewModels 下更新資料區域的ViewModel。

 1 using Demo10A_Framework.Core;
 2 using Demo10A_Framework.Globals;
 3 using Demo10A_Infrastructure.DTO;
 4 using Demo10A_Models;
 5 using System;
 6 using System.Collections.Generic;
 7 using System.Collections.ObjectModel;
 8 using System.Linq;
 9 using System.Text;
10 using System.Threading.Tasks;
11 using System.Windows.Controls;
12 
13 namespace Demo10A_Framework.ViewModels
14 {
15     public class PDataViewModel:BaseViewModel
16     {
17         private DataManager<TableUserInfo> _users;
18         public DataManager<TableUserInfo> Users
19         {
20             get { return _users; }
21             set { _users = value; RaisePropertyChanged(); }
22         }
23         public DelegateCommand ControlButtonCommand
24         {
25             get
26             {
27                 return new DelegateCommand(ControlButtonCommand_Executed);
28             }
29         }
30         private void ControlButtonCommand_Executed(object obj)
31         {
32             if(obj is string)
33             {
34                 EnumControlButton cb = Enum.Parse<EnumControlButton>(obj as string);
35                 switch (cb)
36                 {
37                     case EnumControlButton.NavHome:
38                         _users.NavHome();
39                         break;
40                     case EnumControlButton.NavPrevious:
41                         _users.NavPrevious();
42                         break;
43                     case EnumControlButton.NavFirst:
44                         _users.NavFirst();
45                         break;
46                     case EnumControlButton.NavSecond:
47                         _users.NavSecond();
48                         break;
49                     case EnumControlButton.NavThird:
50                         _users.NavThird();
51                         break;
52                     case EnumControlButton.NavFourth:
53                         _users.NavFourth();
54                         break;
55                     case EnumControlButton.NavFifth:
56                         _users.NavFifth();
57                         break;
58                     case EnumControlButton.NavNext:
59                         _users.NavNext();
60                         break;
61                     case EnumControlButton.NavEnd:
62                         _users.NavEnd();
63                         break;
64                     default:
65                         break;
66                 }
67             }
68         }
69 
70         public PDataViewModel()
71         {
72             var user = new UserInfo();
73             _users = new DataManager<TableUserInfo>(user.QueryAllUserInfo());
74         }
75     }
76 }
PDataViewModel.cs

②模組 Demo10A-Framework 資料夾 Views 下更新資料區域的View。

 1 <Page x:Class="Demo10A_Framework.Views.PDataView"
 2       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5       xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6       xmlns:local="clr-namespace:Demo10A_Framework.Views" xmlns:converters="clr-namespace:Demo10A_Framework.Converters"
 7       mc:Ignorable="d" 
 8       d:DesignHeight="450" d:DesignWidth="800"
 9       Title="PDataView">
10     <Page.Resources>
11         <converters:ConvertBool2Visibility x:Key="visibilityConvert"/>
12     </Page.Resources>
13     <Grid>
14         <Grid.RowDefinitions>
15             <RowDefinition/>
16             <RowDefinition Height="30"/>
17         </Grid.RowDefinitions>
18         <DataGrid ItemsSource="{Binding Users.ItemSource}" SelectedItem="{Binding Users.SelectedItem}"/>
19         <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
20             <Button Content="{Binding Users.NavHomeContent}" Visibility="{Binding Users.NavHomeVisibility,Converter={StaticResource visibilityConvert}}" Width="40" Command="{Binding ControlButtonCommand}" CommandParameter="NavHome"/>
21             <Button Content="{Binding Users.NavPreviousContent}" Visibility="{Binding Users.NavPreviousVisibility,Converter={StaticResource visibilityConvert}}" Width="40" Command="{Binding ControlButtonCommand}" CommandParameter="NavPrevious"/>
22             <Button Content="{Binding Users.NavFirstContent}" Visibility="{Binding Users.NavFirstVisibility,Converter={StaticResource visibilityConvert}}" Width="40" Command="{Binding ControlButtonCommand}" CommandParameter="NavFirst"/>
23             <Button Content="{Binding Users.NavSecondContent}" Visibility="{Binding Users.NavSecondVisibility,Converter={StaticResource visibilityConvert}}" Width="40" Command="{Binding ControlButtonCommand}" CommandParameter="NavSecond"/>
24             <Button Content="{Binding Users.NavThirdContent}" Visibility="{Binding Users.NavThirdVisibility,Converter={StaticResource visibilityConvert}}" Width="40" Command="{Binding ControlButtonCommand}" CommandParameter="NavThird"/>
25             <Button Content="{Binding Users.NavFourthContent}" Visibility="{Binding Users.NavFourthVisibility,Converter={StaticResource visibilityConvert}}" Width="40" Command="{Binding ControlButtonCommand}" CommandParameter="NavFourth"/>
26             <Button Content="{Binding Users.NavFifthContent}" Visibility="{Binding Users.NavFifthVisibility,Converter={StaticResource visibilityConvert}}" Width="40" Command="{Binding ControlButtonCommand}" CommandParameter="NavFifth"/>
27             <Button Content="{Binding Users.NavNextContent}" Visibility="{Binding Users.NavNextVisibility,Converter={StaticResource visibilityConvert}}" Width="40" Command="{Binding ControlButtonCommand}" CommandParameter="NavNext"/>
28             <Button Content="{Binding Users.NavEndContent}" Visibility="{Binding Users.NavEndVisibility,Converter={StaticResource visibilityConvert}}" Width="40" Command="{Binding ControlButtonCommand}" CommandParameter="NavEnd"/>
29         </StackPanel>
30     </Grid>
31 </Page>
PDataView.xaml

③模組 Demo10A-Framework 資料夾 Globals 下新增資料分頁管理類DataManager.cs。

  1 using Demo10A_Framework.Core;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Collections.ObjectModel;
  5 using System.Linq;
  6 using System.Text;
  7 using System.Threading.Tasks;
  8 
  9 namespace Demo10A_Framework.Globals
 10 {
 11     public class DataManager<T>: NotificationObject
 12     {
 13         private ObservableCollection<T> _itemSource;
 14         public ObservableCollection<T> ItemSource { get { return _itemSource; } set { _itemSource = value; RaisePropertyChanged(); } }
 15         public T SelectedItem { get; set; }
 16 
 17         #region 繫結控制按鈕屬性
 18         private EnumControlButton _controlButton;
 19         public EnumControlButton ControlButton
 20         {
 21             get { return _controlButton; }
 22             set { _controlButton = value; RaisePropertyChanged(); }
 23         }
 24 
 25         private string _navHomeContent = "首頁";
 26         public string NavHomeContent { get { return _navHomeContent; } set { _navHomeContent = value; RaisePropertyChanged(); } }
 27         private bool _navHomeVisibility;
 28         public bool NavHomeVisibility { get { return _navHomeVisibility; } set { _navHomeVisibility = value; RaisePropertyChanged(); } }
 29         private string _navPreviousContent = "上一頁";
 30         public string NavPreviousContent { get { return _navPreviousContent; } set { _navPreviousContent = value; RaisePropertyChanged(); } }
 31         private bool _navPreviousVisibility;
 32         public bool NavPreviousVisibility { get { return _navPreviousVisibility; } set { _navPreviousVisibility = value; RaisePropertyChanged(); } }
 33         private int _navFirstContent = 1;
 34         public int NavFirstContent { get { return _navFirstContent; } set { _navFirstContent = value; RaisePropertyChanged(); } }
 35         private bool _navFirstVisibility;
 36         public bool NavFirstVisibility { get { return _navFirstVisibility; } set { _navFirstVisibility = value; RaisePropertyChanged(); } }
 37         private int _navSecondContent = 2;
 38         public int NavSecondContent { get { return _navSecondContent; } set { _navSecondContent = value; RaisePropertyChanged(); } }
 39         private bool _navSecondVisibility;
 40         public bool NavSecondVisibility { get { return _navSecondVisibility; } set { _navSecondVisibility = value; RaisePropertyChanged(); } }
 41         private int _navThirdContent = 3;
 42         public int NavThirdContent { get { return _navThirdContent; } set { _navThirdContent = value; RaisePropertyChanged(); } }
 43         private bool _navThirdVisibility;
 44         public bool NavThirdVisibility { get { return _navThirdVisibility; } set { _navThirdVisibility = value; RaisePropertyChanged(); } }
 45         private int _navFourthContent = 4;
 46         public int NavFourthContent { get { return _navFourthContent; } set { _navFourthContent = value; RaisePropertyChanged(); } }
 47         private bool _navFourthVisibility;
 48         public bool NavFourthVisibility { get { return _navFourthVisibility; } set { _navFourthVisibility = value; RaisePropertyChanged(); } }
 49         private int _navFifthContent = 5;
 50         public int NavFifthContent { get { return _navFifthContent; } set { _navFifthContent = value; RaisePropertyChanged(); } }
 51         private bool _navFifthVisibility;
 52         public bool NavFifthVisibility { get { return _navFifthVisibility; } set { _navFifthVisibility = value; RaisePropertyChanged(); } }
 53         private string _navNextContent = "下一頁";
 54         public string NavNextContent { get { return _navNextContent; } set { _navNextContent = value; RaisePropertyChanged(); } }
 55         private bool _navNextVisibility;
 56         public bool NavNextVisibility { get { return _navNextVisibility; } set { _navNextVisibility = value; RaisePropertyChanged(); } }
 57         private string _navEndContent = "尾頁";
 58         public string NavEndContent { get { return _navEndContent; } set { _navEndContent = value; RaisePropertyChanged(); } }
 59         private bool _navEndVisibility;
 60         public bool NavEndVisibility { get { return _navEndVisibility; } set { _navEndVisibility = value; RaisePropertyChanged(); } }
 61         #endregion
 62 
 63         public void NavHome()
 64         {
 65             if (_currentPageNumber >= 1)
 66             {
 67                 ShowPage(1);
 68             }
 69         }
 70         public void NavPrevious()
 71         {
 72             if (_currentPageNumber > 1)
 73             {
 74                 ShowPage(_currentPageNumber - 1);
 75             }
 76         }
 77         public void NavFirst()
 78         {
 79             ShowPage(NavFirstContent);
 80         }
 81         public void NavSecond()
 82         {
 83             ShowPage(NavSecondContent);
 84         }
 85         public void NavThird()
 86         {
 87             ShowPage(NavThirdContent);
 88         }
 89         public void NavFourth()
 90         {
 91             ShowPage(NavFourthContent);
 92         }
 93         public void NavFifth()
 94         {
 95             ShowPage(NavFifthContent);
 96         }
 97         public void NavNext()
 98         {
 99             if (_currentPageNumber < _maxPageNumber)
100             {
101                 ShowPage(_currentPageNumber + 1);
102             }
103         }
104         public void NavEnd()
105         {
106             if (_maxPageNumber >= 1)
107             {
108                 ShowPage(_maxPageNumber);
109             }
110         }
111 
112 
113         private List<T> _dataSource;
114         private int _pageCount = 8;
115         private int _currentPageNumber = 1;
116         private int _maxPageNumber;
117 
118         public DataManager(List<T> data)
119         {
120             _dataSource = data;
121             //初始化顯示
122             //1、計算最大頁數
123             _maxPageNumber = (int)Math.Ceiling(_dataSource.Count * 1.0 / _pageCount);
124             if (_maxPageNumber == 1)
125             {
126                 NavFirstVisibility = true;
127             }
128             else if (_maxPageNumber > 1)
129             {
130                 NavHomeVisibility = true;
131                 NavPreviousVisibility = true;
132                 NavNextVisibility = true;
133                 NavEndVisibility = true;
134                 if (_maxPageNumber > 1)
135                 {
136                     NavFirstVisibility = true;
137                     NavSecondVisibility = true;
138                 }
139                 if (_maxPageNumber > 2)
140                 {
141                     NavThirdVisibility = true;
142                 }
143                 if (_maxPageNumber > 3)
144                 {
145                     NavFourthVisibility = true;
146                 }
147                 if (_maxPageNumber > 4)
148                 {
149                     NavFifthVisibility = true;
150                 }
151             }
152             ShowPage(1);
153         }
154         private void ShowPage(int pageNumber)
155         {
156             //更新資料
157             _currentPageNumber = pageNumber;
158             ItemSource = new ObservableCollection<T>(_dataSource.Skip(_pageCount * (pageNumber - 1)).Take(_pageCount));
159        
160             //更新按鈕
161             if(pageNumber != _navThirdContent)
162             {
163                 if(pageNumber==_navFirstContent)
164                 {
165                     if (_navFirstContent > 2)
166                     {
167                         UpdateShowPageNumber(-2);
168                     }
169                     else if (_navFirstContent > 1)
170                     {
171                         UpdateShowPageNumber(-1);
172                     }
173                 }
174                 else if(pageNumber == _navSecondContent)
175                 {
176                     if (_navFirstContent > 1)
177                     {
178                         UpdateShowPageNumber(-1);
179                     }
180                 }
181                 else if(pageNumber == _navFifthContent)
182                 {
183                     if (_maxPageNumber - _navFifthContent >= 2)
184                     {
185                         UpdateShowPageNumber(2);
186                     }
187                     else if (_maxPageNumber - _navFifthContent >= 1)
188                     {
189                         UpdateShowPageNumber(1);
190                     }
191                 }
192                 else if(pageNumber == _navFourthContent)
193                 {
194                     if (_maxPageNumber - _navFifthContent >= 1)
195                     {
196                         UpdateShowPageNumber(1);
197                     }
198                 }
199                 else
200                 {
201                     if (pageNumber - _navFifthContent >= 2)
202                     {
203                         UpdateShowPageNumber(2);
204                     }
205                     else if (pageNumber - _navFifthContent >= 1)
206                     {
207                         UpdateShowPageNumber(1);
208                     }
209                     else if (_navFirstContent - pageNumber >= 2)
210                     {
211                         UpdateShowPageNumber(-2);
212                     }
213                     else if (_navFirstContent - pageNumber >= 1)
214                     {
215                         UpdateShowPageNumber(-1);
216                     }
217                 }
218             }
219         
220         }
221         private void UpdateShowPageNumber(int count)
222         {
223             NavFirstContent = NavFirstContent + count;
224             NavSecondContent = NavSecondContent + count;
225             NavThirdContent = NavThirdContent + count;
226             NavFourthContent = NavFourthContent + count;
227             NavFifthContent = NavFifthContent + count;
228         }
229 
230 
231     }
232 
233     public enum EnumControlButton
234     {
235         NavHome,
236         NavPrevious,
237         NavFirst,
238         NavSecond,
239         NavThird,
240         NavFourth,
241         NavFifth,
242         NavNext,
243         NavEnd
244     }
245 }
DataManager.cs

④模組 Demo10A-Models 更新使用者資訊業務UserInfo.cs。

 1 using Demo10A_Infrastructure.DTO;
 2 using Demo10A_Infrastructure.Utility;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Text.Json;
 6 
 7 namespace Demo10A_Models
 8 {
 9     public class UserInfo
10     {
11         public string UserName { get; set; }
12         public string Password { get; set; }
13         public LoginResult Login()
14         {
15             var tUser= DBHelper.QueryByUsername(UserName);
16             if (tUser.Password.Equals(Password))
17             {
18                 
19                 return new LoginResult { Success=true,Message=string.Format("登入成功:{0}", JsonSerializer.Serialize(tUser)),User= tUser };
20             }
21             return new LoginResult { Success = false, Message = "密碼不匹配" };
22         }
23         public List<TableUserInfo> QueryAllUserInfo()
24         {
25             return DBHelper.QueryAllUserInfo();
26         }
27     }
28 }
UserInfo.cs

⑤以上就完成了資料分頁顯示的功能。

 

4、框架使用

  稍後補充
5、參考

  kiba518的部落格  https://www.cnblogs.com/kiba/category/1291917.html