亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

如何搭建新的WPF項目框架

2020-01-24 01:35:15
字體:
來源:轉載
供稿:網友

下面就WPF項目框架搭建步驟一步一步的分享給大家。

在WPF項目開發中最常用的開發模式無疑是MVVM模式,  MVVM模式開發的好處,在這里就不詳細討論, 還有 本文中所使用MVVMLight框架,為什么使用MVVM框架(1、框架較輕,2、學習成本低、3、適用大多數中小型項目,4、相對于微軟的prism框架更容易上手)   
下面開始 一步一步 搭建框架

第一步: 利用反射創建VM構造器

 

public class ViewModelFactory{ private static Dictionary<string, object> vmMap = new Dictionary<string, object>();<br> public static T GetViewModel<T>() where T : ViewModelBase {  Type vmType = typeof(T);  if (vmMap.ContainsKey(vmType.FullName))  {   return (T)vmMap[vmType.FullName];  }  else  {   object vm = Activator.CreateInstance(vmType);   vmMap.Add(vmType.FullName, vm);   return (T)vm;  } } public static T GetViewModel<T>(object[] data,string id) where T : ViewModelBase {  Type vmType = typeof(T);  if (vmMap.ContainsKey(id))  {   return (T)vmMap[id];  }  else  {   object vm = Activator.CreateInstance(vmType, data);   vmMap.Add(id, vm);   return (T)vm;  } }}

為什么用一個Dictionary  將ViewModel  緩存起來,相信利用MVVM模式開發大多數的開發者碰到的問題無疑是各個VM之間的數據通信問題,利用Dictionary緩存起來有兩個好處:

1、可以解決VM之間相互通信的問題(當然你也可以用MvvmLight的 Message機制來通信,PS:個人認為完全沒必要用MvvmLight中的 Messgae,如果我們框架搭的合理完全可以規避去用MvvmLight中 Message,Message比較難于管理,如果在我們的代碼中出現大量的Message無疑是一件痛苦的事情,所以筆者不推薦用MvvmLight中的Message)

2、如果我們的應用程序要頻繁的與服務器做交互,我們完全可以用緩存,以避免每次都去請求服務器(可以緩存一些在應用程序中一直使用的數據,規避二次請求)

public static T GetViewModel<T>() where T : ViewModelBase  這個函數(將我們的VM完全限定名作為KEY緩存)適用于單例模式的VM,

public static T GetViewModel<T>(object[] data,string id) where T : ViewModelBase 這個函數(主要構件帶參數的VM構造函數,id是唯一ID),為什么會用到它,舉個例子

例如我們的QQ聊天窗口,所有聊天窗口基本相同用到的VM類型也是相同,所以這時候就需要多個VM實例了,第一種方法就行不通了 所以會用到這種方法去構建VM,并將id作為KEY值緩存起來

第二步:構建我們的ViewModel 基類:

public delegate void CloseEventHandle(object sender); public class CustomViewModel : ViewModelBase {  public event CloseEventHandle CloseEvent; protected bool hasData;  public CustomViewModel()  {  LoadCommand = new RelayCommand(() =>   {    if (!hasData)    {     ThreadPool.QueueUserWorkItem((obj) =>     {      lock (this)      {       OnLoad();       hasData = true;      }     });    }   });  }public RelayCommand LoadCommand { private set; get; }  protected virtual void OnLoad()  {  }  protected void OnClose(object sender)  {   if (sender != null && CloseEvent != null)   {    CloseEvent(sender);   }  } }

上面CustomViewModel 繼承的ViewModelBase 是MvvmLight中的ViewModelBase,至于MvvmLight用法不在本文中討論,

1、為什么要聲明LoadCommand,因為大多數的時候我們會在窗體或用戶控件Loaded的時候去加載數據,有可能是異步加載,也有可能是同步加載,所以我們在CustomViewModel中

聲明省去了各個VM子類中去聲明LoadCommand的麻煩,使用時我們直接在XAML利用MvvmLight提供的EventToCommand 去綁定LoadCommand,然后在對應的VM去重寫CustomViewModel基類中的OnLoad方法就可以了。

2、CloseEvent 故名思議是用來在VM中關閉窗體用的(詳細用法會在下文中討論)

3、我們也可以將一些公有的數據都提煉到VM中來。

第三步  管理窗口:

  在開發程序的時候我們通常要去管理窗口的如果你沒用到MVVM模式 或者是傳統的Winform 你可以隨便的去new Window(),或者隨便的去改Window的構造函數,或者隨意的去構造單例窗體,但是如果用到了MVVM模式似乎以上所說的一切都變得復雜了,剛開始的時候我也是挺傷腦筋的,后來在不斷的重構代碼中找到了解決方法,(PS:本人也是一名菜鳥,只想把自己在開發中的問題及解決方法分享出來,未必就是好的解決方案,所以大神們勿噴)下面上代碼: 構建我們的ShowHelper類:


public class ShowHelper {  private static Dictionary<string, Window> windowManager = new Dictionary<string, Window>();  public static void ShowDiaglogUc<T>(string title, object[] constructors = null, bool isDialog = false) where T : UserControl  {   Type controlType = typeof(T);   string key;   if (constructors == null) //如果構造參數為null   {    key = controlType.FullName; //key = T 的完全限定名   }   else   {    // 如果不為空 并且 第二個構造參數為string(第二個參數代表id -->有可能是GroupId 有可能是UserId);    if (constructors.Length == 2 && constructors[1] is string) //ps:這里本人寫死了可以根據需求自行修改    {     key = controlType.FullName + constructors[1].ToString(); //key = 控件 完全限定名+id;    }    else //不滿足條件    {     key = controlType.FullName; //key = 限定名    }   }   if (windowManager.ContainsKey(key)) //如果包含KEY   {    windowManager[key].Topmost = true; //設置TopMost    return;   }   UserControl content;   if (constructors == null)   {    content = Activator.CreateInstance(controlType) as UserControl;   }   else   {    content = Activator.CreateInstance(controlType, constructors) as UserControl;   }   BaseWindow window = new BaseWindow(); //PS這是自己封裝 的Window,(可以用直接用原始的Wpf Widnow)   window.Title = title;   windowManager.Add(key, window);   window.Closed += (sen, cloE) =>   {    windowManager.Remove(key);   };   if (isDialog)   {    window.ShowDialog();   }   else   {    window.Show();   }   #region 注冊關閉事件   if (content.DataContext as CustomViewModel != null)   {    CustomViewModel vm = content.DataContext as CustomViewModel;    vm.CloseEvent += (obj) =>    {     if (content.DataContext.Equals(obj))     {      window.Close();     }    };   }   #endregion  }  public static CustomDialogResult ShowOkCancleUC<T>(string title, MsgBoxBtn okCancle, out object data) where T : Control  {   Type vmType = typeof(T);   Control content = Activator.CreateInstance(vmType) as Control;   OkCanleWindow window = new OkCanleWindow();   window.ShowInTaskbar = false;   return window.ShowDialog(title, okCancle, content, out data);  }  public static CustomDialogResult MessageBoxDialog(string title, string message, MsgBoxBtn okCancle)  {   OkCanleWindow window = new OkCanleWindow();   window.ShowInTaskbar = false;   object none;   return window.ShowDialog(title, okCancle, new MessageUC() { Message = message }, out none);  }、(1)開始剖析 public static void ShowDiaglogUc<T>(string title, object[] constructors = null, bool isDialog = false) where T : UserControl  ShowDialogUc 是用來在VM中用來創建UserControl并顯示在Window中的。你可能會問為啥用windowManager 將窗口緩存起來(PS這里主要還是為了解決單例窗口的麻煩),  至于 下面這段代碼,我們可以回到創建的CustomerViewModel中,對這里需要注冊VM中CloseEvent事件,這樣我們在VM中就可以直接調用OnClose()方法就OK了  #region 注冊關閉事件   if (content.DataContext as CustomViewModel != null)   {    CustomViewModel vm = content.DataContext as CustomViewModel;    vm.CloseEvent += (obj) =>    {     if (content.DataContext.Equals(obj))     {      window.Close();     }    };   }  #region 注冊關閉事件

(2)開始剖析 public static void ShowDiaglogUc<T>(string title, object[] constructors = null, bool isDialog = false) where T : UserControl 函數中的 constructors 參數

  在開始剖析 constructors 之前先讓我們 聯想一下應用場景(可以先想下,QQ的聊天窗口,例如群聊天吧,所有的群聊天都是相同界面,也就是說他們所對應的VM應該是統一類型的      VM,如果我們雙擊群,則會彈出對應相應的聊天窗口,正常的思維是會給聊天窗口傳遞參數也就是組ID 這時候我們的VM就需要構造參數了,還有一個問題就是每個群組聊天窗口只能有一個,總不能每次雙擊就new一個聊天窗口了吧 所以這時候我們就需要做緩存了,) 綜上constructors參數在配合ViewModelFactory中的 public static T GetViewModel<T>(object[] data,string id) where T : ViewModelBase 方法  可以解決我們VM中需要傳遞參數的問題,windowManager 可以解決窗口緩存問題(如果你現在還看不明白請 仔細看上面代碼(雖然代碼有點渣),如果實在看不明白可以在留言板吐槽)。

1、 開始 剖析 public static CustomDialogResult ShowOkCancleUC<T>(string title, MsgBoxBtn okCancle, out object data) where T : Control

  (1)開始剖析該函數前讓我們 新建一個自己的帶返回值的 ShowDialog 窗口

     新建xaml窗口

<controls:BaseWindow x:Class="Common.OkCanleWindow"  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  xmlns:controls="clr-namespace:Controls;assembly=Controls"  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  Title="MessageBoxWindow"> <Grid x:Name="grid">  <Grid.RowDefinitions>   <RowDefinition/>   <RowDefinition Height="50"/>  </Grid.RowDefinitions>  <Grid.ColumnDefinitions>   <ColumnDefinition/>   <ColumnDefinition/>  </Grid.ColumnDefinitions>  <Button Content="確 定" x:Name="okBtn" Click="okBtn_Click" Grid.Row="1" Height="30" Width="120" HorizontalAlignment="Right" Margin="0 0 10 0"/>  <Button Content="取 消" x:Name="canleBtn" Click="canleBtn_Click" Grid.Row="1" Grid.Column="1" Height="30" Width="120" HorizontalAlignment="Left" Margin="10 0 0 0"/> </Grid></controls:BaseWindow>  后臺代碼:public partial class OkCanleWindow : BaseWindow {  public OkCanleWindow()  {   InitializeComponent();this.Closed += (s, e) =>    {     if (result == CustomDialogResult.None)     {      result = CustomDialogResult.Cancel;     }    };  }  private System.Windows.Controls.Control control;  CustomDialogResult result;  public CustomDialogResult ShowDialog(string title, MsgBoxBtn btnState, Control uc, out object dataContext)  {   #region 設置控件   if (btnState == MsgBoxBtn.Ok) //如果為OK狀態   {    Grid.SetColumnSpan(okBtn, 2); //設置OK按鈕跨兩列    okBtn.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; //設置OK按鈕居中對齊    canleBtn.Visibility = System.Windows.Visibility.Collapsed; //設置Cancel 按鈕隱藏;    if (uc != null)    {     control = uc;       Grid.SetRow(uc, 0); //設置控件所在Grid 的行     Grid.SetColumnSpan(uc, 2); //設置控件所在Grid 的列     this.Width = uc.Width; //設置窗體寬度     this.Height = uc.Height + grid.RowDefinitions[1].Height.Value + 35; //設置窗體寬度 高度     grid.Children.Add(uc); //加入控件    }   }   if (btnState == MsgBoxBtn.None) //如果為None 既沒有OK 也沒有 Cancle   {    grid.RowDefinitions.RemoveAt(1);    okBtn.Visibility = System.Windows.Visibility.Collapsed;    canleBtn.Visibility = System.Windows.Visibility.Hidden;    if(uc !=null)    {     control = uc;     Grid.SetRow(uc, 0); //設置控件所在Grid 的行     Grid.SetColumnSpan(uc, 2); //設置控件所在Grid 的列     this.Width = uc.Width; //設置窗體寬度     this.Height = uc.Height + 35;     grid.Children.Add(uc); //加入控件    }   }      this.Title = title;   dataContext = uc.DataContext;   #endregion   this.ShowDialog();return result;  }  private void okBtn_Click(object sender, RoutedEventArgs e)  {   result = CustomDialogResult.OK;   this.Close();  }  private void canleBtn_Click(object sender, RoutedEventArgs e)  {   result = CustomDialogResult.Cancel;   this.Close();  } } public enum CustomDialogResult  {  None,OK,Cancel } public enum MsgBoxBtn  {  None,Ok,OkCancel }

剖析 ShowDialog(string title, MsgBoxBtn btnState, Control uc, out object dataContext) 方法

在Control uc 代表我們要ShowDialog的UC,dataContext 可以輸出一些數據,另外我們要自定義一些枚舉

public static CustomDialogResult MessageBoxDialog(string title, string message, MsgBoxBtn okCancle)  主要用來顯示自定義MessageBoxUserControl;和上面得方法差不多,

以上分為三大步驟對WPF 項目框架搭建的介紹,并結合代碼做剖析,希望對大家有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩国产中文精品字幕自在自线| 欧美成人性生活| 亚洲人a成www在线影院| 亚洲精品福利在线观看| 久久国内精品一国内精品| 亚洲第一福利网站| 国产三级精品网站| 成人免费视频网| 亚洲欧美在线一区| 日韩精品在线免费观看视频| 国产精品亚洲片夜色在线| 国产视频亚洲视频| 国产成人aa精品一区在线播放| 美女福利精品视频| 爽爽爽爽爽爽爽成人免费观看| 亚洲欧美另类自拍| 国产精品网址在线| 日韩精品一区二区三区第95| 亚洲社区在线观看| 久久久久久久国产精品| 日韩国产高清污视频在线观看| **欧美日韩vr在线| 国产精品亚洲片夜色在线| 国产高清视频一区三区| 亚洲综合精品伊人久久| 亚洲第一男人av| 国产亚洲精品成人av久久ww| 国产欧美久久久久久| 日韩视频―中文字幕| 在线观看日韩欧美| 久久久精品欧美| 国产拍精品一二三| 亚洲第一精品福利| 欧美洲成人男女午夜视频| 国产日韩欧美中文在线播放| 久久在线精品视频| 国产999视频| 亚洲精品国产精品国产自| 美女少妇精品视频| 欧美大片免费观看在线观看网站推荐| 在线播放国产一区中文字幕剧情欧美| 成人女保姆的销魂服务| 精品久久久一区二区| 久久99久久99精品中文字幕| 国产欧美最新羞羞视频在线观看| 青青久久av北条麻妃海外网| 亚洲精品久久在线| 日韩成人在线电影网| 日韩av在线网址| 久久国产精品久久国产精品| 日韩精品在线观看视频| 欧美午夜丰满在线18影院| 丝袜美腿亚洲一区二区| 中文字幕日韩专区| 国产精品视频公开费视频| 久久精品成人动漫| 欧美日韩免费在线| 欧洲s码亚洲m码精品一区| 欧美美女18p| 精品日本高清在线播放| 成人黄色av免费在线观看| 午夜欧美大片免费观看| 国产精品国产三级国产专播精品人| 亚洲第一区在线观看| 精品视频—区二区三区免费| 日韩国产高清污视频在线观看| 欧美激情精品久久久久久蜜臀| 日韩视频永久免费观看| 欧美日本精品在线| 久久精品男人天堂| 日韩精品在线视频观看| 欧美一级bbbbb性bbbb喷潮片| 成人免费淫片aa视频免费| 国产日韩欧美成人| 亚洲精品久久久久久久久久久久| 国产精品久久久久久久久久三级| 国产亚洲欧洲高清| 欧美激情免费视频| 久久精品视频网站| 久久精品久久久久| 国产精品扒开腿爽爽爽视频| 国产精品三级网站| 国产日本欧美一区二区三区| 中文字幕综合在线| 欧美在线xxx| 欧美亚洲激情视频| 日韩免费精品视频| 国产精品一区二区三区久久久| 中文字幕精品一区二区精品| 国产精品老女人精品视频| 奇米4444一区二区三区| 91精品国产乱码久久久久久蜜臀| 国产国语刺激对白av不卡| 色综合色综合久久综合频道88| 91中文字幕在线观看| 欧美激情精品久久久久久久变态| 8050国产精品久久久久久| 91精品国产高清久久久久久久久| 97热精品视频官网| 欧美日韩精品中文字幕| 久久夜色精品国产欧美乱| 亚洲人成网7777777国产| 2018国产精品视频| 亚洲色图第一页| 国产成人精品免费视频| 国产日韩欧美成人| 久久成人这里只有精品| 国产亚洲视频在线观看| 精品二区三区线观看| 亚洲国产小视频在线观看| 亚洲第一色中文字幕| 欧美成人黑人xx视频免费观看| 国产日韩欧美成人| 精品香蕉一区二区三区| 国产精品欧美在线| 国产suv精品一区二区三区88区| 精品女厕一区二区三区| 国产精品美女在线| 九九视频直播综合网| 日韩专区在线观看| 色999日韩欧美国产| 91久久久久久| 欧美亚洲视频在线观看| 亚洲网站在线看| 国产成人精品亚洲精品| 欧美有码在线视频| 欧美大全免费观看电视剧大泉洋| 欧美精品在线免费播放| 日日摸夜夜添一区| 成人黄色大片在线免费观看| 亚洲第一av网站| 久久久久久亚洲精品| 亚洲美女在线视频| 欧美午夜精品久久久久久浪潮| 欧美丝袜美女中出在线| 国产有码在线一区二区视频| 欧美黄网免费在线观看| 欧美一区二区影院| 国产精品一区专区欧美日韩| 精品亚洲精品福利线在观看| 中文字幕亚洲情99在线| 日韩国产高清污视频在线观看| 国产精品精品视频一区二区三区| 国产综合视频在线观看| 国产亚洲精品日韩| 久久精品国产欧美激情| 国产精品久久久久一区二区| 国产精品专区第二| 亚洲石原莉奈一区二区在线观看| 91精品国产成人www| 亚洲电影中文字幕| 久久久中精品2020中文| 91地址最新发布| 亚洲最大的免费| 国产精品www色诱视频| 亚洲最新av在线网站| 日韩不卡在线观看| 97视频免费观看| 欧美xxxx18国产| 欧美电影在线免费观看网站| 色综合91久久精品中文字幕| 91网站在线看| 久久成人精品一区二区三区| 亚洲视频综合网|