wpf之三:WPF的MVVM模式
2.Model
Model就是一個class,是對現實中事物的抽象,開發過程中涉及到的事物都可以抽象為Model,例如客戶,客戶的姓名、編號、電話、住址等屬性也對應了class中的Property,客戶的下訂單、付款等行為對應了class中的方法。
3. View
View很好理解,就是介面。對應WPF中的xaml介面設計。
4. ViewModel
上面說過Model抽象,那麼ViewModel就是對View的抽象。顯示的資料對應著ViewMode中的Property,執行的命令對應著ViewModel中的Command。
5.WPF中MVVM的解耦方式
在WPF的MVVM模式中,View和ViewModel之間資料和命令的關聯都是通過繫結實現的,繫結後View和ViewModel並不產生直接的依賴。具體就是View中出現數據變化時會嘗試修改繫結的目標。同樣View執行命令時也會去尋找繫結的Command並執行。反過來,ViewModel在Property發生改變時會發個通知說“名字叫XXX的Property改變了,你們這些View中誰綁定了XXX也要跟著變啊!”,至於有沒有View收到是不是做出變化也不關心。ViewModel中的Command脫離View就更簡單了,因為Command在執行操作過程中操作資料時,根本不需要操作View中的資料,只需要操作ViewModel中的Property就可以了,Property的變化通過繫結就可以反映到View上。這樣在測試Command時也不需要View的參與。這也是我在接觸WPF初期時根本理解不了的所謂資料驅動。這樣一來ViewMode可以在完全沒有View的情況下測試,View也可以在完全沒有ViewModel的情況下測試(當然只是測試介面佈局和動畫等業務無關的內容)。
二.資料繫結
首先定義NotificationObject類。目的是繫結資料屬性。這個類的作用是實現了INotifyPropertyChanged介面。WPF中類要實現這個介面,其屬性成員才具備通知UI的能力在Prism中有一個NotificationObject自動實現了這個介面,位於Microsoft.Practices.Prism.ViewModel名稱空間下。也就是說,Prism推薦ViewModel繼承這個NotificationObject類來自動實現INotifyPropertyChanged介面。
1.定義Model
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Practices.Prism.Commands; using Microsoft.Practices.Prism.ViewModel; namespace WpfMsgReport.Model { //航次號Model class BaseCommonModel:NotificationObject { private string code; public string Code { get { return code; } set { code = value; this.RaisePropertyChanged("Code"); } } private string name; public string Name { get { return name; } set { name = value; this.RaisePropertyChanged("Name"); } } private string other; public string Other { get { return other; } set { other = value; this.RaisePropertyChanged("Other"); } } } }
2.定義ViewModel:ViewModel有屬性VoyNoList
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Practices.Prism.Commands; using Microsoft.Practices.Prism.ViewModel; using System.Windows.Forms; using WpfMsgReport.Model; namespace WpfMsgReport.ViewModel { //主頁面ViewModel class MainWindowViewModel : NotificationObject { /// <summary> /// 航次號列表 /// </summary> private List<BaseCommonModel> voyNoList; public List<BaseCommonModel> VoyNoList { get { return voyNoList; } set { voyNoList = value; this.RaisePropertyChanged("VoyNoList"); } } public MainWindowViewModel(HelpNavigator MyNavigator) { //載入主介面資料 this.loadMainData(); } /// <summary> /// 載入主介面資料 /// </summary> private void loadMainData() { //載入航次號列表 this.VoyNoList = new List<BaseCommonModel>(); BaseCommonModel voyNoModel = new BaseCommonModel(); voyNoModel.Code = "10000"; voyNoModel.Name = "10000"; VoyNoList.Add(voyNoModel); BaseCommonModel voyNoModel1 = new BaseCommonModel(); voyNoModel1.Code = "10001"; voyNoModel1.Name = "10001"; VoyNoList.Add(voyNoModel1); } } }
3.View控制元件繫結ViewModel的屬性VoyNoList
<ComboBox x:Name="voyNoList" ItemsSource="{Binding VoyNoList}" DisplayMemberPath="Name" SelectedValuePath="Code" SelectionChanged="voyNoList_SelectionChanged"/>
xaml對應的.cs的DataContext設定為MainWindowViewModel
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfMsgReport.Model;
using WpfMsgReport.ViewModel;
namespace WpfMsgReport
{
/// <summary>
/// MainWindow.xaml 的互動邏輯
/// </summary>
public partial class MainWindow : Window
{
System.Windows.Forms.HelpNavigator MyNavigator = System.Windows.Forms.HelpNavigator.TableOfContents;
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel(MyNavigator);
}
}
}
實現效果:
三.命令繫結
1.ViewModel定義命令並繫結實現方法
程式碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.ViewModel;
using System.Windows.Forms;
using WpfMsgReport.Model;
using System.Windows;
namespace WpfMsgReport.ViewModel
{
//主頁面ViewModel
class MainWindowViewModel : NotificationObject
{
/// <summary>
/// 航次號列表
/// </summary>
private List<BaseCommonModel> voyNoList;
public List<BaseCommonModel> VoyNoList
{
get { return voyNoList; }
set
{
voyNoList = value;
this.RaisePropertyChanged("VoyNoList");
}
}
///命令
public DelegateCommand<object> SendMailCommand { get; set; } //傳送報文按鈕
public MainWindowViewModel(HelpNavigator MyNavigator)
{
this.SendMailCommand = new DelegateCommand<object>(SendMailCommandExecute);
//載入主介面資料
this.loadMainData();
}
/// <summary>
/// 載入主介面資料
/// </summary>
private void loadMainData()
{
//載入航次號列表
this.VoyNoList = new List<BaseCommonModel>();
BaseCommonModel voyNoModel = new BaseCommonModel();
voyNoModel.Code = "10000";
voyNoModel.Name = "10000";
VoyNoList.Add(voyNoModel);
BaseCommonModel voyNoModel1 = new BaseCommonModel();
voyNoModel1.Code = "10001";
voyNoModel1.Name = "10001";
VoyNoList.Add(voyNoModel1);
}
/// <summary>
/// 選擇報文,傳送郵件
/// </summary>
/// <param name="obj"></param>
private void SendMailCommandExecute(object obj)
{
UIElement ui = obj as UIElement;
if (ui != null)
{
if (ui.GetType().Name == "DataGrid")
{
System.Windows.Controls.DataGrid dg = ui as System.Windows.Controls.DataGrid;
var a = dg.SelectedItem;
System.Windows.Forms.MessageBox.Show("傳送郵件");
}
}
}
}
}
2.在xaml的控制元件繫結命令,並把介面控制元件作引數傳遞到ViewModel的方法中
程式碼如下:
<Button Width="100" Cursor="Hand" Background="White" BorderBrush="White" Command="{Binding Path=SendMailCommand}" CommandParameter="{Binding ElementName=reportListDataGrid}">
<StackPanel Orientation="Horizontal">
<Image HorizontalAlignment="Center" VerticalAlignment="Center" Source="/WpfMsgReport;component/Images/email.gif" Height="16"/>
<TextBlock Text="傳送郵件" Width="70" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="2,0,0,0" />
</StackPanel>
</Button>
3.實現效果
四.事件繫結
WPF中不是所有的控制元件都有Command屬性的,如窗體,如果需要在ViewModel中處理Loaded事件命令,或者其他事件的命令時,很難通過繫結Command完成,必須要註冊依賴屬性或事件等,太麻煩了。我喜歡簡約、有效的方式,現在我和大家一起分享一下。
場景,我需要處理ComboBox的SelectionChanged事件,但又避免用後置程式碼,儘量要在ViewModel中獲取。這是需要一個System.Windows.Interactivity.dll,該dll是安裝Blend後才有的,在C:\Program Files\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries目錄中,然後我們仍需要Prism.dll。
1.在ViewModel定義命令ChangeVoyNoCommand
2.在ViewModel實現方法ChangeVoyNoCommandExecute
3.在xaml中匯入System.Windows.Interactivity.dll
4.在控制元件ComboBox上繫結事件SelectionChanged和命令ChangeVoyNoCommand
<ComboBox x:Name="voyNoList" ItemsSource="{Binding VoyNoList,UpdateSourceTrigger=PropertyChanged}" SelectedValue="{Binding Path=SelectVoyNo, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Name" SelectedValuePath="Code">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding ChangeVoyNoCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
5.實現效果
相關推薦
wpf之三:WPF的MVVM模式
2.Model Model就是一個class,是對現實中事物的抽象,開發過程中涉及到的事物都可以抽象為Model,例如客戶,客戶的姓名、編號、電話、住址等屬性也對應了class中的Property,客戶的下訂單、付款等行為對應了class中的方法。 3. View View很好理解,就是介面。對應WPF
設計模式介紹之三:命令模式(command)
命令(模式)的結構很簡單,但對於消除程式碼間的耦合卻有著重要的影響。 在 C 語言中我們經常使用回撥函式,而命令模式是回撥( callback )的面向物件的替代物。從最直觀的角度來看,命令模式就是一個函式物件:一個作為物件的函式。通過將函式封裝為物件,就能
設計模式系列之三:工廠模式(Factory Pattern)
這是本系列的第三篇部落格,這次主要來說一下工廠模式。 基本工廠模式 簡單來說工廠模式是將工程中的相同型別物件的建立活動集中管理,一般通過反射來生成外界需要的實體類。比如Spring中的容器Bean概念,通過Spring BeanFactory來產生不同的Be
設計模式之三:單例模式(餓漢式與懶漢式)
//保證類在記憶體中只有一個物件 package com.xjh.demo.designpattern.pattern3; public class Student { private Student(){ } //懶漢式 priva
設計模式之三:工廠方法模式—多型工廠的實現
簡單工廠的嚴重問題: 當系統中需要引進新產品時,靜態工廠方法通過所傳入引數的不同來建立不同的產品,這必定要修改工廠類的原始碼,違背了開閉原則 引入工廠方法模式: 針對不同的產品提供不同的工廠 定義: 定義一個用於建立物件的介面,讓子類決定將 哪一個類例項化,工廠方法迷失
hadoop初識之三:搭建hadoop環境(配置HDFS,Yarn及mapreduce 執行在yarn)上及三種執行模式(本地模式,偽分散式和分散式介)
--===============安裝jdk(解壓版)================== --root 使用者登入 --建立檔案層級目錄 /opt下分別 建 modules/softwares/datas/tools 資料夾 --檢視是否安裝jdk rpm -
設計模式系列之三:抽象工廠模式
前言 在設計模式有三個模式是與工廠模式相關的,分別是:簡單工廠模式、工廠方法模式以及抽象工廠模式。在前面的文章中已經談到前面兩種,這裡就對抽象工廠模式介紹一下。抽象工廠模式就是提供一個建立一系列相關或者相互依賴的介面(也就是抽象類),而無需指定具體的類。簡單來
設計模式之三:迭代器模式
1. 前言 迭代器模式(Iterator)提供了一種方法,它可以順序訪問一個物件當中的各個元素,但是又不暴露這個聚合物件的內部標示。聽起來和遍歷很像,個人感覺就是遍歷,即是,迭代器提供了一個方法,可以順序物件內部的某個容器,而不用知道容器中存放的是什麼型別.在
設計模式之三:抽象工廠模式
抽象工廠模式(Abstract Factory Pattern): 定義:Provide an interface for creating families of related or dependent objects without specify
CNCF CNI系列之三:flannel vxlan模式工作原理淺析
一、前言flannel為container提供網路解決方案。flannel有一個基於etcd cluster的資料交換中心,每個節點上有flannel service,每個節點被分配不同的網段,每個節點上的container從該網段獲取IP。一個節點之間通過一個overlay
RabbitMQ指南之三:發布/訂閱模式(Publish/Subscribe)
問題 除了 消息 模型 server fan 以及 color let 在上一章中,我們創建了一個工作隊列,工作隊列模式的設想是每一條消息只會被轉發給一個消費者。本章將會講解完全不一樣的場景: 我們會把一個消息轉發給多個消費者,這種模式稱之為發布-訂閱模式。 為了
RabbitMQ指南之三:釋出/訂閱模式(Publish/Subscribe)
在上一章中,我們建立了一個工作佇列,工作佇列模式的設想是每一條訊息只會被轉發給一個消費者。本章將會講解完全不一樣的場景: 我們會把
VCSA 6.5 HA配置 之三 :準備工作
vmware vcenter ha 高可用 vcsa 接著上一篇文章部署完成VCSA 6.5後,還需要做一些準備工作才能開啟高可用功能,本篇文章主要就講述如何為vCenter 高可用進行準備工作配置vCenter HA網絡從vCenter HA的架構圖中可以看出對於vCenter HA的高
Linux學習之三:文件夾系統的結構和相對(絕對)路徑
sharp 二進制 沒有 數據 csharp pan 用戶 ont 臨時 理解每個目錄的作用 bin 二進制文件 boot 系統的啟動文件、內核 dev 設備文件 etc 配置文件 home 用戶的家目錄 lib 鏈接庫文件 l
RabbitMQ系列教程之三:發布/訂閱(Publish/Subscribe)
mqc 標題 整合 參數 cti 事情 return 控制臺 run (本教程是使用Net客戶端,也就是針對微軟技術平臺的) 在前一個教程中,我們創建了一個工作隊列。工作隊列背後的假設是每個任務會被交付給一個【工人】。在這一部分我們將做一些完全不同的事情--我們將向多個
OSPF詳解之三:OSPF LSA詳解
ospf lsa詳解 forwarding address OSPF LSA詳解OSPF V2版本中常用的主要有6類LSA,分別是Router-LSA、Network-LSA、Network-summary-LSA、ASBR-summary-LSA、AS-External-LSA、NSSA-LSA,接
設計模式之八:組合模式(Composite Pattern)
數據結構 log ide ase 統一 etc 方法 可能 模式 什麽是組合模式呢?簡單來說組合模式就是將對象合成樹形結構以表示“部分整體”的層次結構,組合模式使用戶對單個對象和組合對象使用具有一致性。 組合模式(Composite Pattern)有時
Django運維後臺的搭建之三:用url去精細定制與反向解析
django 反向解析 參數傳遞 url指向 上一篇文章裏,我們做了一個alionlineecs(阿裏雲線上環境服務器)的添加界面,但是要知道我們的計劃裏是有六個分支的,而alionlineecs僅僅是其中之一,要是每一個都這麽寫的話,那麽views.py肯定又臭又長,充滿了大量的復制片段。對
camera攝像原理之三:色溫和自動白平衡【轉】
mil gho 實現 技術分享 處理 目標 紅旗 適應 如果 轉自:http://blog.csdn.net/ghostyu/article/details/7912863 色溫的定義:將黑體從絕對零度開始加溫,溫度每升高一度稱為1開氏度(用字母K表示),當溫度升高到一定
Halcon學習之三:有關圖像通道的函數
spa com detail too pan targe 個數 word pop 黑白攝像機會返回每個像素所對應的能量采用結果,這些結果組成了一幅單通道灰度值圖像,而對於RGB彩色攝像機,它將返回每個像素所對應的三個采樣結果,也就是一幅三通道圖像。下面這些是與圖像通道有關的