講講Windows10(UWP)下的Binding

前言

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

今天講講XAML中的Binding打毛。沒啥技術(shù)含量柿赊,全當是快速閱讀。

Binding作為MVVM模式的一個相對核心的功能幻枉,一直是有爭議的碰声。使用數(shù)據(jù)綁定可以將我們的View和Model解耦,但是如果一旦出現(xiàn)Bug熬甫,我們將很難調(diào)試胰挑,還有一個問題就是數(shù)據(jù)綁定會帶來過大的內(nèi)存開銷。
跟多數(shù)的技術(shù)一樣椿肩,都有自己的兩面性瞻颂,具體運用場景如何抉擇,應(yīng)該充分考慮郑象。

作為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; }
}

微軟設(shè)計了一個Binding的基礎(chǔ)模型,蘊含了接口分離原則(ISP)的思想拔妥,又提供了一個IBindingBase的空接口忿危,如果你想實現(xiàn)自己的Binding模型,可以繼承這個接口没龙,這樣可以和.NET類庫風格統(tǒng)一铺厨。

講講IBinding

既然我們已經(jīng)了解了Binding的大概的層次結(jié)構(gòu)缎玫,那我們開始一個個講講這些都是怎么用的。

IBinding中的Path

Path是我們相對用的比較多的解滓,多數(shù)情況下赃磨,我們可以這樣寫

Text="{Binding}"

XAML會取綁定源的ToString的值,所以我們可以重寫Override方法來實現(xiàn)我們的需要的綁定洼裤。
我們也可以綁定具體的屬性邻辉,比如:

Text="{Binding Name}"

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

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

除了上述比較常用的逸邦,我們還有一個叫做ICustomPropertyProvider的接口恩沛,當你的類實現(xiàn)了這個接口中的

string GetStringRepresentation() 

XAML就會去取這個函數(shù)返回的值。

所以總結(jié)下我們的Path的綁定方式:

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

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

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

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

IBinding中的Mode

Mode一共有三種缕减,OneTime雷客,OneWay,TwoWay桥狡〗寥梗看字面的意思就很容易理解。

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

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

  • 對于普通的屬性,需要類實現(xiàn)INotifyPropertyChanged嫂易,并且對象值變化時手動通知變更兄朋。
  • 對于依賴屬性,當觸發(fā)SetValue方法后怜械,PropertyChangedCallBack會通知變更颅和,所以無需我們手動操作。
    在UWP系統(tǒng)中缕允,Mode的默認值為OneWay峡扩。

IBinding中的RelativeSource

RelativeSource是一種相對關(guān)系找數(shù)據(jù)源的綁定。目前有兩種: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名稱范圍里驾霜。
  • 如果綁定目標位于數(shù)據(jù)模板或控件模板中案训,則為模板化父級的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三者是互斥的猜旬,指定多余一種的綁定方式會引發(fā)異常脆栋。

IBinding中的Converter

我們很難保證我們的對象值和我們綁定目標的類型一直倦卖,所以轉(zhuǎn)換器可以將類型就行轉(zhuǎn)換。
使用轉(zhuǎn)換器我們要實現(xiàn)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();
    }
}

如果你的值需要轉(zhuǎn)換回去椿争,你也可以繼續(xù)實現(xiàn)ConvertBack方法怕膛。

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

IBinding中的ConverterParameter和ConverterLanguage

這兩個參數(shù)不能綁定,只能指定常量值秦踪。

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

IBinding中的參數(shù)基本上覆蓋了我們多數(shù)的需求褐捻。盡管相對于WPF缺少了多值綁定等等,但我們也能夠通過自定義一些附加屬性來實現(xiàn)這些功能椅邓。

IBinding2

IBinding2中的參數(shù)就相對使用的比較少了柠逞。

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合住。
多數(shù)情況下大多數(shù)依賴項屬性的默認值都為 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; 
}

有關(guān)uwp的Binding就說到這里僚害。謝謝~

參考資料

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

個人推薦

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末硫椰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子萨蚕,更是在濱河造成了極大的恐慌靶草,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件门岔,死亡現(xiàn)場離奇詭異,居然都是意外死亡烤送,警方通過查閱死者的電腦和手機寒随,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帮坚,“玉大人妻往,你說我怎么就攤上這事∈院停” “怎么了讯泣?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長阅悍。 經(jīng)常有香客問我好渠,道長昨稼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任拳锚,我火速辦了婚禮假栓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘霍掺。我一直安慰自己匾荆,他們只是感情好,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布杆烁。 她就那樣靜靜地躺著牙丽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪兔魂。 梳的紋絲不亂的頭發(fā)上烤芦,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機與錄音入热,去河邊找鬼拍棕。 笑死,一個胖子當著我的面吹牛勺良,可吹牛的內(nèi)容都是我干的绰播。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼尚困,長吁一口氣:“原來是場噩夢啊……” “哼蠢箩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起事甜,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤谬泌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后逻谦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掌实,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年邦马,在試婚紗的時候發(fā)現(xiàn)自己被綠了贱鼻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡滋将,死狀恐怖邻悬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情随闽,我是刑警寧澤父丰,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站掘宪,受9級特大地震影響蛾扇,放射性物質(zhì)發(fā)生泄漏攘烛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一屁桑、第九天 我趴在偏房一處隱蔽的房頂上張望医寿。 院中可真熱鬧,春花似錦蘑斧、人聲如沸靖秩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沟突。三九已至,卻和暖如春捕传,著一層夾襖步出監(jiān)牢的瞬間惠拭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工庸论, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留职辅,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓聂示,卻偏偏與公主長得像域携,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鱼喉,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理秀鞭,服務(wù)發(fā)現(xiàn),斷路器扛禽,智...
    卡卡羅2017閱讀 134,656評論 18 139
  • 很多時候我們需要將某個View1 值的改變顯示在另外一個View2 上锋边,對View1的對應(yīng)事件編碼可實現(xiàn)我們想要的...
    MayueCif閱讀 4,007評論 2 3
  • 什么是Xaml Xaml(Extensible Application Markup Language) 可擴展應(yīng)...
    北風知我意閱讀 651評論 0 1
  • 目錄 什么是WPF? WPF的歷史编曼? 為什么要用WPF及WPF作用 WPF與winForm區(qū)別豆巨? 什么是WPF? ...
    灬52赫茲灬閱讀 5,811評論 2 11
  • 近段時期掐场,校園暴力充斥著我們的朋友圈:中關(guān)村二小被同學(xué)欺凌往扔;山西運城少年被同學(xué)圍歐致死;重慶彭水學(xué)生廁所內(nèi)被同學(xué)殺...
    ef8371372682閱讀 1,446評論 0 1