程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 若何搭建新的WPF項目框架

若何搭建新的WPF項目框架

編輯:C#入門知識

若何搭建新的WPF項目框架。本站提示廣大學習愛好者:(若何搭建新的WPF項目框架)文章只能為提供參考,不一定能成為您想要的結果。以下是若何搭建新的WPF項目框架正文


上面就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 項目框架搭建的引見,並聯合代碼做分析,願望對年夜家有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved