講講Windows10(UWP)下的Binding

来源:http://www.cnblogs.com/youngytj/archive/2016/01/22/5152329.html
-Advertisement-
Play Games

前言 貌似最近來問我XAML這塊的東西的人挺多的。有時候看他們寫XAML這塊覺著也挺吃力的,所謂基礎不牢,地動山搖。XAML這塊雖說和HTML一樣屬於標記語言,但是世界觀相對更加龐大一點。 今天講講XAML中的Binding。沒啥技術含量,全當是快速閱讀。 Binding作為MVVM模式的一個...


前言

貌似最近來問我XAML這塊的東西的人挺多的。有時候看他們寫XAML這塊覺著也挺吃力的,所謂基礎不牢,地動山搖。XAML這塊雖說和HTML一樣屬於標記語言,但是世界觀相對更加龐大一點。

今天講講XAML中的Binding。沒啥技術含量,全當是快速閱讀。

Binding作為MVVM模式的一個相對核心的功能,一直是有爭議的。使用數據綁定可以將我們的View和Model解耦,但是如果一旦出現Bug,我們將很難調試,還有一個問題就是數據綁定會帶來過大的記憶體開銷。
跟多數的技術一樣,都有自己的兩面性,具體運用場景如何抉擇,應該充分考慮。

作為XAML的一部分,Binding的功能也隨著XAML版本的變更著。目前為止,XAML一共有以下幾個版本:

  • WPF Version
  • Silverlight 3 Version
  • Silverlight 4 Version
  • Windows 8 XAML/Jupiter(Windows Runtime XAML Framework) Version

其中WPF版本的Binding功能最強大,但也開銷最大。本文中,我們主要講述最新版本,即__Windows 8 XAML/Jupiter__這個版本的XAML中的Binding。

開始之前

要想講明白Binding這個東西,我們先要從Binding類的繼承層次開始講。

public class Binding : BindingBase, IBinding, IBinding2
{
    public Binding();

    public IValueConverter Converter { get; set; }
    public System.String ConverterLanguage { get; set; }
    public System.Object ConverterParameter { get; set; }
    public System.String ElementName { get; set; }
    public BindingMode Mode { get; set; }
    public PropertyPath Path { get; set; }
    public RelativeSource RelativeSource { get; set; }
    public System.Object Source { get; set; }
    
    public System.Object FallbackValue { get; set; }   
    public System.Object TargetNullValue { get; set; }
    public UpdateSourceTrigger UpdateSourceTrigger { get; set; }
}

可以看到Binding繼承了BindingBase類,還繼承了IBinding,IBinding2的介面。我們再分別看下這三個類和介面。首先看下我們的BindingBase。

public class BindingBase : DependencyObject, IBindingBase
{
    public BindingBase();
}

BindingBase又繼承了DependencyObject和IBindingBase。DependencyObject這個我們就不多講了,IBindingBase只是一個空介面。看來BindingBase沒有看到太多信息,我們再來看下IBinding和IBinding2。

internal interface IBinding
{
    IValueConverter Converter { get; set; }
    System.String ConverterLanguage { get; set; }
    System.Object ConverterParameter { get; set; }
    System.String ElementName { get; set; }
    BindingMode Mode { get; set; }
    PropertyPath Path { get; set; }
    RelativeSource RelativeSource { get; set; }
    System.Object Source { get; set; }
}
internal interface IBinding2
{
    System.Object FallbackValue { get; set; }
    System.Object TargetNullValue { get; set; }
    UpdateSourceTrigger UpdateSourceTrigger { get; set; }
}

微軟設計了一個Binding的基礎模型,蘊含了介面分離原則(ISP)的思想,又提供了一個IBindingBase的空介面,如果你想實現自己的Binding模型,可以繼承這個介面,這樣可以和.NET類庫風格統一。

講講IBinding

既然我們已經瞭解了Binding的大概的層次結構,那我們開始一個個講講這些都是怎麼用的。

IBinding中的Path

Path是我們相對用的比較多的,多數情況下,我們可以這樣寫

Text="{Binding}"

XAML會取綁定源的ToString的值,所以我們可以重寫Override方法來實現我們的需要的綁定。
我們也可以綁定具體的屬性,比如:

Text="{Binding Name}"

如果我們綁定了一個集合,那我們也可以嘗試這樣寫:

Text="{Binding MyList[1].Name}"

除了上述比較常用的,我們還有一個叫做ICustomPropertyProvider的介面,當你的類實現了這個介面中的

string GetStringRepresentation() 

XAML就會去取這個函數返回的值。

所以總結下我們的Path的綁定方式:

預設情況:
target Text="{Binding}"
source ToString()
//你可以重寫ToString方法來改變值

屬性綁定:
target Text="{Binding Name}"
source public String Name { get;}

索引器綁定:
target Text="{Binding MyList[1].Name}"

實現ICustomPropertyProvider的綁定:
target Text="{Binding}"
source String GetStringRepresentation() 
//實現方法獲取值

IBinding中的Mode

Mode一共有三種,OneTime,OneWay,TwoWay。看字面的意思就很容易理解。

//OneTime
Text="{Binding, Mode=OneTime}"
//OneWay
Text="{Binding, Mode=OneWay}"
//TwoWay
Text="{Binding, Mode=TwoWay}"

在OneWay和TwoWay中,如果想要對象的值變更時讓綁定目標也變化,需要註意一下兩點

  • 對於普通的屬性,需要類實現INotifyPropertyChanged,並且對象值變化時手動通知變更。
  • 對於依賴屬性,當觸發SetValue方法後,PropertyChangedCallBack會通知變更,所以無需我們手動操作。
    在UWP系統中,Mode的預設值為__OneWay__。

IBinding中的RelativeSource

RelativeSource是一種相對關係找數據源的綁定。目前有兩種:Self和TemplatedParent

//Self
<TextBlock Text="{Binding Foreground.Color.R, RelativeSource={RelativeSource Mode=Self}}" Foreground="Red"/>

//TemplatedParent
<DataTemplate> 
    <Rectangle Fill="Red" Height="30" Width="{Binding Width, RelativeSource={RelativeSource Mode=TemplatedParent}}">
</DataTemplate>  

RelativeSource綁定的方式我們常用於控制項模板。預設值一般為null。

IBinding中的ElementName

ElementName也是我們最常用的一種綁定方式,使用這個我們需要註意兩點:

  • 指定的ElementName必須在當前XAML名稱範圍里。
  • 如果綁定目標位於數據模板或控制項模板中,則為模板化父級的XAML名稱範圍。
    舉個例子:
<UserControl x:Name="Instance" Background="Red"> 
  <Grid Background="{Binding Background, ElementName=Instance}"/> 
</UserControl> 
//or
<Page x:Name="Instance"> 
  <Grid> 
    <ItemsControl ItemsSource="{Binding Users}"> 
      <ItemsControl.ItemTemplate> 
        <DataTemplate> 
          <Button Command=" {Binding DataContext.TestCommand, ElementName=Instance}"/> 
        </DataTemplate> 
      </ItemsControl.ItemTemplate> 
    </ItemsControl> 
   </Grid> 
 </Page> 

IBinding中的Source

Source也是我們常用的一種方式。

<Page> 
  <Page.Resources> 
    <SolidColorBrush x:Key="MainBrush" Color="Orange"/> 
  </Page.Resources> 
  <Grid Background="{Binding Source={StaticResource MainBrush}}"/> 
</Page>
//當然我們也可以簡寫為
<Grid Background="{StaticResource MainBrush}"/>

一般情況下,Source,ElementName和RelativeSource三者是互斥的,指定多餘一種的綁定方式會引發異常。

IBinding中的Converter

我們很難保證我們的對象值和我們綁定目標的類型一直,所以轉換器可以將類型就行轉換。
使用轉換器我們要實現IValueConverter介面:

public class BoolVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        bool? result = value as Nullable<bool>;
        if(result == true)
        {
            return Visibility.Visible;
        }
        return Visibility.Collapsed;

    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

如果你的值需要轉換回去,你也可以繼續實現ConvertBack方法。

<Page> 
  <Page.Resources> 
    <local:BoolVisibilityConverter x:Key="BoolVisibilityConverter"/> 
  </Page.Resources> 
  <Grid> 
    <Border Visibility="{Binding Busy, Converter={StaticResource BoolVisibilityConverter}}"/> 
  </Grid> 
</Page>

IBinding中的ConverterParameter和ConverterLanguage

這兩個參數不能綁定,只能指定常量值。

<Border Visibility="{Binding Busy, Converter={StaticResource BoolVisibilityConverter}, 
  ConverterParameter=One, ConverterLanguage=en-US}"/> 

IBinding中的參數基本上覆蓋了我們多數的需求。儘管相對於WPF缺少了多值綁定等等,但我們也能夠通過自定義一些附加屬性來實現這些功能。

IBinding2

IBinding2中的參數就相對使用的比較少了。

IBinding2中的FallbackValue

FallbackValue的用途是:當綁定對象不存在時,我們就使用FallbackValue的值:

<Page> 
  <Page.Resources> 
    <x:String x:Key="ErrorString">Not Found</x:String> 
  </Page.Resources> 
  <Grid> 
    <TextBlock Text="{Binding Busy, FallbackValue={StaticResource ErrorString}}"/> 
  </Grid> 
</Page>

IBinding2中的TargetNullValue

TargetNullValue的用途是:當綁定對象為空時,我們就使用TargetNullValue的值:

<Page> 
  <Page.Resources> 
    <x:String x:Key="ErrorString">Not Found</x:String> 
  </Page.Resources> 
  <Grid> 
    <TextBlock Text="{Binding Busy, TargetNullValue={StaticResource ErrorString}}"/> 
  </Grid> 
</Page>

IBinding2中的UpdateSourceTrigger

UpdateSourceTrigger的值有三種:Default,PropertyChanged,Explicit。
多數情況下大多數依賴項屬性的預設值都為 PropertyChanged。但是Text屬性不是。
PropertyChanged的意思是當綁定目標屬性更改時,立即更新綁定源。而Explicit是只有UpdateSource方法時才更新綁定源。
舉個例子:

<Grid> 
    <TextBox x:Name="TitleTextBox" Text="{Binding Title, ElementName=Instance, UpdateSourceTrigger=Explicit, Mode=TwoWay}" /> 
    <Button Click="Button_Click"/> 
</Grid>


private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    var current = this.Title; 
    TitleTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource(); 
    current = this.Title; 
}

有關uwp的Binding就說到這裡。謝謝~

參考資料

被誤解的MVC和被神化的MVVM
Extensible Application Markup Language
RelativeSource 標記擴展
UpdateSourceTrigger enumeration

個人推薦

我的博客園
我的簡書
我的Github


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

-Advertisement-
Play Games
更多相關文章
  • 1、配置redis master,redis slave(配置具體操作見上文http://www.cnblogs.com/wangchaozhi/p/5140469.html)。redis master ip:127.0.0.1:port 6379(預設配置文件即可)redis slave1 ip:...
  • 作為一個網站開發者,使用asp.net開髮網站,由於添加功能模塊不便利,所以我開始學習mvc框架。 今天是我學習mvc框架的第一天,首先就是連接EF連接資料庫(Sql Server2012資料庫),下麵我使用圖片和文字來描述我的過程。1.首先創建控制台應用程式(使用的框架是4.5),然後再控制...
  • https://ajaxcontroltoolkit.codeplex.com/警告 7 未能找到引用的組件“Antlr3.Runtime”。 警告 6 未能找到引用的組件“HtmlAgilityPack”。 警告 10 未能找到引用的組件“HtmlAgilityPack”。 警告 1 未能找到引用...
  • 10-9. 在多對多關係中為插入和刪除使用存儲過程問題想要在一個無載荷的多對多關係中使用存儲過程(存儲過程隻影響關係的連接表)解決方案假設有一個多對多關係的作者( Author)表和書籍( Book)表. 用連接表AuthorBook來做多對多關係,如 Figure 10-11.所示:Figure ...
  • 第一章 初識Windows程式01.淺談控制台應用 解析:控制台應用程式:dos視窗中顯示 Windows窗體應用程式:有控制項參與的,支持事件的一種程式02.關於窗體項目的註意點: /*01.一個解決方案下可以包含多個項目, * 一個項目下可以包含多個窗體 * 02.如何設置一個項目下的某個窗體為啟...
  • ADO.NET操作使用ADO.NET的方式操作資料庫時,對於經常需要操作不同資料庫的同學,需要對不同的資料庫翻來覆去地寫操作類。<br 對ADO.NET,操作資料庫需要有幾個核心的東西(以MySql為例): MySqlConnection 負責mysql的連接,在操作mysql前,需要先獲得連接.....
  • 前臺管理主界面:主要代碼: 1 2 private void MainForm_Load(object sender, EventArgs e) 3 { 4 // 載入時,運行播放窗體 5 FrmPlay play...
  • 10-8. 映射插入、修改、刪除操作到存儲過程問題想要映射插入、修改、刪除操作到存儲過程解決方案假設已有運動員實體模型,如Figure 10-8所示. 對應的資料庫表如Figure 10-9所示. 我們想要用存儲過程來執行插入,修改,刪除操作。Figure 10-8. 運動員實體模型Figure 1...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...