【我們一起寫框架】MVVM的WPF框架(二)—綁定

来源:https://www.cnblogs.com/kiba/archive/2018/09/10/9610364.html
-Advertisement-
Play Games

MVVM的特點之一是實現數據同步,即,前臺頁面修改了數據,後臺的數據會同步更新。 上一篇我們已經一起編寫了框架的基礎結構,並且實現了ViewModel反向控制Xaml窗體。 那麼現在就要開始實現數據同步了。 DataContext—數據上下文 在實現數據同步前,我們要瞭解一個知識點——DataCon ...


MVVM的特點之一是實現數據同步,即,前臺頁面修改了數據,後臺的數據會同步更新。

上一篇我們已經一起編寫了框架的基礎結構,並且實現了ViewModel反向控制Xaml窗體。

那麼現在就要開始實現數據同步了。

DataContext—數據上下文

在實現數據同步前,我們要瞭解一個知識點——DataContext。

WPF中每個UI都有一個Content和一個DataContext,那麼Content和DataContext是什麼呢?

Content:Content是指頁面內容,即我們編寫的代碼,或者認為它是展示的UI。

打個比方,Content就是HTML頁面中的標簽,如【<html></html】;那麼,在WPF中Content是指的就是Xaml頁面的標簽了。

DataContext:DataContext是指頁面中的數據內容,這部分內容只有運行了才存在,用過ASP.NET MVC的同學可以把它理解為MVC中的Model。(每個頁面都有一個唯一的指定Model)

既然在WPF里DataContext就是MVC中的Model。那麼,自然的,DataContext就要存儲頁面的ViewModel了,所以,我們為它賦值它自身對應的ViewModel。

現在,找到我們的BaseViewModel的構造函數,加入這行代碼[UIElement.DataContext = this;],代碼如下:

public BaseViewModel()
{
    WindowMain = Application.Current.MainWindow; 
    SetUIElement();
    UIElement.DataContext = this;
}

這樣用ViewModel創建的頁面的DataContext就被自動賦值了。

頁面與ViewModel的基礎關係就建立完成了。

Binding—綁定

在我們編寫的框架中,綁定分兩種,一種是屬性綁定,一種是命令綁定。

屬性綁定:屬性綁定很好理解,就是將Xaml頁面的控制項屬性和ViewModel中的自定義屬性捆綁到一起,讓他們的數據值同步。

命令綁定:命令綁定是Xaml頁面觸發命令,然後由ViewModel來處理命令。

這裡的命令(Command)有點不太好理解,不過大家都做過面向事件的開發,我們可以把命令想象成事件,就是Xaml頁面觸發事件,ViewModel來執行事件內容。

接下來,我們一起做一些簡單的綁定。

Property—屬性綁定

首先,在程式框架中找到VM_WindowMain頁面,然後在裡面創建屬性HeaderName,代碼如下:

public string _HeaderName = "HeaderName_KibaFramework";
public string HeaderName { get { return _HeaderName; } set { _HeaderName = value; OnPropertyChanged(); } }

然後,我們再找到VM對應的Xam頁面—WindowMain.xaml,修改Header代碼如下:

<StackPanel  DockPanel.Dock="Top" Background="Gainsboro">
    <TextBlock TextAlignment="Left" Text="{Binding HeaderName}" Margin="20,20,0,0" Height="70" FontSize="36"></TextBlock>
</StackPanel>

界面效果如下:

通過圖片,我們可以看到,屬性已經綁定成功了,並且成功輸出了我們的HeaderName。

然後,我們重點看一下這段代碼{Binding HeaderName}。

這句話的意思就是讓TextBlock的Text屬性綁定HeaderName屬性,其中Binding就是綁定的意思。【註意,這裡只能是屬性綁定屬性】

HeaderName是我們在VM中剛剛定義的屬性,那麼Text是怎麼綁定到了HeaderName上的呢?

很簡單,因為上面我們已經把ViewModel賦值到了DataContext中了,所以在Xaml中,我們就可以使用{Binding 屬性名}這樣的語句,來綁定VM中所有的屬性。

在Xaml中,TextBlock預設的綁定是單向綁定,就是說,VM中的屬性值改變會同步Xaml頁面的屬性值,讓其改變;但,當Xaml頁面的屬性值改變了,VM中的屬性值卻不會改變。

那麼如何讓他們同步呢?

很簡單,只需要在綁定的時候多加一個屬性Mode=TwoWay即可,代碼如下:

{Binding HeaderName,Mode=TwoWay}

Command—命令綁定

在MVVM中,事件被極大的程度的弱化了,因為Command在ViewModel中替代了事件來處理業務邏輯,所以,事件在框架中就只負責處理UI變化這麼一件事了。 

BaseCommand

在WPF中,系統為我們提供一些Command,但為了能處理更多細節,自定義Command的效果會更好,所以,我們需要編寫屬於我們框架自己的自定義BaseCommand。

代碼如下:

public class BaseCommand : ICommand
{
    public Action<object> ExecuteAction;
    public BaseCommand(Action<object> action)
    {
        ExecuteAction = action;
    }
    public bool CanExecute(object parameter)
    {
        return true;
    } 
    public event EventHandler CanExecuteChanged;
    public void Execute(object parameter)
    { 
        ExecuteAction(parameter); 
    } 
}

如上代碼所示,我們自定義了BaseCommand,並且繼承了ICommand介面,實現了介面方法。

Command的應用

下麵我們開始Command的基礎應用,使用Command實現頁面切換;頁面切換我們採用最簡單的模式Window—Frame—Page的控制模式。

首先我們找到VM_WindowMain,創建切換Page的Command和存儲頁面實例的屬性FrameSource。

代碼如下:

public Page _FrameSource;
public Page FrameSource { get { return _FrameSource; } set { _FrameSource = value; OnPropertyChanged(); } } 
public BaseCommand ChangeFrameSourceCommand
{
    get
    {
        return new BaseCommand(ChangeFrameSourceCommand_Executed);
    }
}
public void ChangeFrameSourceCommand_Executed(object obj)
{
    string pageName = obj.ToString();
   switch(pageName)
   {
       case "PageMain":
           FrameSource = new VM_PageMain().UIElement as Page;
           break;
       case "PageUser":
           FrameSource = new VM_PageUser().UIElement as Page;
           break;
   }
}

接下來在頁面實現按鈕事件綁定和Frame顯示頁面綁定。

代碼如下:

<TreeViewItem>
    <TreeViewItem.Template>
        <ControlTemplate>
            <Button HorizontalAlignment="Left" Content="PageMain" Command="{Binding ChangeFrameSourceCommand}" CommandParameter="PageMain"  Style="{StaticResource NullButton}"></Button>
        </ControlTemplate>
    </TreeViewItem.Template>
</TreeViewItem>
<TreeViewItem>
    <TreeViewItem.Template>
        <ControlTemplate>
            <Button HorizontalAlignment="Left" Content="PageUser" Command="{Binding ChangeFrameSourceCommand}" CommandParameter="PageUser"  Style="{StaticResource NullButton}"></Button>
        </ControlTemplate>
    </TreeViewItem.Template>
</TreeViewItem>

/* 省略了框架其他元素代碼 */

<Frame x:Name="frameMain" Content="{Binding FrameSource,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  NavigationUIVisibility="Hidden" ScrollViewer.CanContentScroll="True"  ></Frame>

從代碼中我們可以看到,VM中的屬性FrameSource綁定到了頁面Frame的Content屬性上。

由於TreeViewItem沒有Command的依賴屬性,所以我們修改了他的模板,然後用模板內的Button的Command屬性綁定了VM中的ChangeFrameSourceCommand屬性。

因為ChangeFrameSourceCommand是BaseCommand類型,所以,當按鈕被按下時,就會觸發ChangeFrameSourceCommand定義的執行命令——ChangeFrameSourceCommand_Executed。

這樣我們就實現了框架內的頁面切換了。

----------------------------------------------------------------------------------------------------

到此,我們框架的基礎功能就已經實現了。

但如果框架只寫到這裡,那ViewModel對頁面的掌控力度就顯的太弱了。

而且項目框架不能僅僅考慮結構分離和業務獨立,我們還要降低使用難度和提高使用者的開發效率。

所以為了更好的掌控UI,降低開發者的門檻,我們還需要編寫數據控制項,讓開發者在不能熟練掌握Xaml樣式的情況下,依然可以順利完成開發。

那麼,本篇文章就先講到這了,下一篇文章我們將一起為框架編寫數據控制項,敬請期待。

框架代碼已經傳到Github上了,並且會持續更新。

相關文章:

【我們一起寫框架】MVVM的WPF框架之序篇(一)

To be continued

Github地址:https://github.com/kiba518/KibaFramework

----------------------------------------------------------------------------------------------------

註:此文章為原創,歡迎轉載,請在文章頁面明顯位置給出此文鏈接!
若您覺得這篇文章還不錯,請點擊下右下角的推薦】,非常感謝!
如果您覺得這篇文章對您有所幫助,那就不妨支付寶小小打賞一下吧。 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ASCII值控制字元ASCII值控制字元ASCII值控制字元ASCII值控制字元 0 NUT 32 (space) 64 @ 96 、 1 SOH 33 ! 65 A 97 a 2 STX 34 " 66 B 98 b 3 ETX 35 # 67 C 99 c 4 EOT 36 $ 68 D 100 ...
  • 調用代理,就是負責將客戶端對服務的調用進行包裝,然後傳遞到伺服器端。當客戶端調用方法時,只是像正常的方法調用一樣,傳入方法參數,取得返回結果。客戶端不需要知道這個調用被傳遞到何處,業務邏輯在哪裡執行。例如: ServiceFactory 使用了 System.Runtime.Remoting.Pro ...
  • 1、Global.asax中添加對Session的支持,重新Init方法: 2、WebConfig中添加跨域支持: 3、寫Session的Controller 4、讀Session的Controller 5、前端jQuery調用時加上參數crossDomain: true 和 xhrFields: ...
  • 1、功能及功能許可權 一般地,用戶擁有一項功能,則應體現在主視窗的功能菜單樹上,功能還應包括業務 View 內部的功能按鈕。框架會根據許可權設定情況使各功能按鈕可用。為了構建導航樹,某些功能還有可能是用來定義導航關係的,而不包含具體的功能含義,舉例說明: 1)用來定義導航關係的功能:如圖所示,【功能】、 ...
  • 初識ASP.NET Core的小伙伴一定會發現,其幾乎所有的項目依賴都是通過依賴註入方式進行鏈式串通的。這是因為其使用了依賴註入 (DI) 的軟體設計模式,代碼的設計是遵循著“高內聚、低耦合”的原則,使得各個類與類之間的關係依賴於介面,這樣做的目的是能更有利於項目代碼的維護與擴展。 ...
  • # [翻譯] 如何在 ASP.Net Core 中使用 Consul 來存儲配置 原文: [USING CONSUL FOR STORING THE CONFIGURATION IN ASP.NET CORE](https://www.natmarchand.fr/consul-configura... ...
  • 1.瀏覽aws 開發人員指南 https://docs.aws.amazon.com/zh_cn/sns/latest/dg/sms_publish-to-phone.html 2.安裝 aws sms net api : AWSSDK.SimpleNotificationService 3.調用  ...
  • 首先說兩件事: 1、大爆炸我還記著呢,先欠著吧。。。 2、博客搬家啦,新地址:https://blog.ultrabluefire.cn/ 下麵是正文 前些日子看到Xaml Controls Gallery的ToggleTheme過渡非常心水,大概是這樣的: 在17134 SDK里寫法如下: 這和我 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...