Xamarin.Forms Data Binding介紹

很多時(shí)候我們需要將某個(gè)View1 值的改變顯示在另外一個(gè)View2 上祟峦,對(duì)View1的對(duì)應(yīng)事件編碼可實(shí)現(xiàn)我們想要的效果宁否,如果只是想處理值的改變副渴,可以通過(guò)連接兩個(gè)View的對(duì)應(yīng)屬性即可翼悴,稱為Data Binding信卡。Data Binding在Model-View-ViewModel (MVVM)設(shè)計(jì)模式中起著重要作用隔缀。
Data Binding中設(shè)計(jì)兩個(gè)概念SourceTarget。當(dāng)Source的值發(fā)生改變時(shí)Data Binding會(huì)自動(dòng)將這個(gè)新的值更新到Target傍菇。對(duì)Target和Source有特殊要求猾瘸,Target必須繼承BindableProperty類(VisualElement通過(guò)繼承Element繼承了BindableObject,所以Xamarin.Forms中視圖的大部分屬性都是BindableProperty類型)丢习,Source必須實(shí)現(xiàn)INotifyPropertyChanged接口提供一種通知機(jī)制監(jiān)聽(tīng)Source值的改變(BindableObject實(shí)現(xiàn)了INotifyPropertyChanged接口)牵触。

簡(jiǎn)單的Data Binding使用

本示例以Slider的Value屬性作Source,Label的Opacity屬性作Target咐低,實(shí)現(xiàn)拖動(dòng)滑塊影響Label透明度的效果揽思。

代碼方式設(shè)置Data Binding:

核心代碼設(shè)置Target對(duì)象的BindingContext屬性(BindableObject類型)。再調(diào)用Target 對(duì)象的SetBinding方法設(shè)置綁定屬性關(guān)系,第一個(gè)參數(shù)targetProperty為BindableProperty類型见擦,表示目標(biāo)屬性钉汗。第二個(gè)參數(shù)string類型,表示BindingContext的哪個(gè)屬性為Source锡宋。本例調(diào)用的是5個(gè)參數(shù)的方法儡湾,后三個(gè)參數(shù)為默認(rèn)值。

代碼運(yùn)行效果:

XAML方式設(shè)置Data Binding:

<StackLayout>
     <Label Text="Opacity Binding Demo"
            FontSize="Large"
            VerticalOptions="CenterAndExpand"
            HorizontalOptions="Center"
            BindingContext="{x:Reference Name=slider}"
            Opacity="{Binding Path=Value}" />

     <Slider x:Name="slider" VerticalOptions="CenterAndExpand" />
</StackLayout>

查看Label定義执俩,BindingContext屬性通過(guò)x:Reference指定徐钠,Opacity為目標(biāo)屬性通過(guò)Binding擴(kuò)展標(biāo)記的Path設(shè)置。Path不僅可以是Property也可以是SubProperty或 Indexer.如Content.Children[4].Value.

在整個(gè)視圖樹(shù)中子View是會(huì)繼承父布局的BindingContext屬性役首。如子View沒(méi)有單獨(dú)設(shè)置BindingContext屬性尝丐,會(huì)查找上級(jí)視圖若發(fā)現(xiàn)BindingContext賦值會(huì)直接繼承,如果上級(jí)視圖同樣沒(méi)有BindingContext賦值且存在上級(jí)視圖會(huì)繼續(xù)搜索上級(jí)視圖BindingContext的賦值衡奥。本例修改XAML布局代碼將Label的BindingContext刪除添加到StackLayout中爹袁,同樣會(huì)實(shí)現(xiàn)我們想要的效果。

<StackLayout BindingContext="{x:Reference Name=slider}">
     <Label Text="Opacity Binding Demo"
            FontSize="Large"
            VerticalOptions="CenterAndExpand"
            HorizontalOptions="Center"
            Opacity="{Binding Path=Value}" />

     <Slider x:Name="slider" VerticalOptions="CenterAndExpand" />
</StackLayout>

同樣可以使用屬性節(jié)點(diǎn)定義方式設(shè)置Data Binding相關(guān)屬性

<Label Text="Opacity Binding Demo"
       FontSize="Large"
       VerticalOptions="CenterAndExpand"
       HorizontalOptions="Center">
       <Label.BindingContext>
            <x:Reference Name="slider" />
        </Label.BindingContext>
    <Label.Opacity>
            <Binding Path="Value" />
        </Label.Opacity>
</Label>

Reference對(duì)應(yīng)的C#類為ReferenceExtension,Binding對(duì)應(yīng)的類為BindingExtension矮固。兩個(gè)類的定義都指定了Content Property失息,分別為Name和Path譬淳,所以可以簡(jiǎn)化代碼:

BindingContext="{x:Reference slider}"
Opacity="{Binding Value}" 

前面是通過(guò)BindingContext指定Data Binding的Source,還可以通過(guò)Binding指定Source盹兢。對(duì)應(yīng)的C#代碼為SetBinding兩個(gè)參數(shù)的方法:

BindingBase為abstract類邻梆,F(xiàn)orms提供了Binding類該類繼承了BindingBase。
通過(guò)Binding指定Source绎秒,再將Binding對(duì)象作為參數(shù)傳入SetBinding方法浦妄。

Binding 提供了重載的構(gòu)造函數(shù)和靜態(tài)方法Create<TSource>來(lái)創(chuàng)建Binding對(duì)象,不作介紹见芹。


構(gòu)造函數(shù)示例

Create<TSource>示例

同樣X(jué)AML定義方式為剂娄,刪除BindingContext屬性賦值,修改Binding擴(kuò)展標(biāo)記玄呛。

根據(jù)內(nèi)容屬性簡(jiǎn)化XAML代碼:

Opacity="{Binding Value , Source={x:Reference slider}}"

擴(kuò)展標(biāo)記定義在一對(duì)大括號(hào)內(nèi)且大括號(hào)內(nèi)不應(yīng)出現(xiàn)雙引號(hào)阅懦,指定多個(gè)屬性值時(shí)通過(guò)逗號(hào)分隔。
關(guān)于內(nèi)容屬性定義的簡(jiǎn)化寫法《Creating Mobile Apps with Xamarin.Forms》中有提到“Even though BindingExtension defines Path as its content property, the argument name can be eliminated only when that argument is the first among multiple arguments.”大概意思是要省略內(nèi)容屬性的參數(shù)名稱必須將其放在第一個(gè)參數(shù),但是測(cè)試發(fā)現(xiàn)Opacity="{Binding Source={x:Reference slider} , Value}"這種寫法同樣可以徘铝。

那么問(wèn)題來(lái)了故黑,如果我們給BindingContext賦值的同時(shí)也為Binding的Source賦值,應(yīng)該將哪個(gè)屬性對(duì)應(yīng)的對(duì)象作為數(shù)據(jù)源庭砍。符合就近原則Source的優(yōu)先級(jí)高于BindingContext场晶,即指定Source時(shí)不在考慮BindingContext。且Source使用更加靈活怠缸,如一個(gè)對(duì)象的多個(gè)屬性使用不同對(duì)象作為數(shù)據(jù)源只能通過(guò)Source方式指定诗轻。


Binding Mode 介紹

現(xiàn)在要通過(guò)Data Binding實(shí)現(xiàn)兩個(gè)Slider的Value相互影響〗冶保滑動(dòng)一個(gè)Slider的同時(shí)另一個(gè)有相同變化扳炬。

愚蠢的辦法是分別將兩個(gè)Slider作為另一個(gè)的Source,即同時(shí)為兩個(gè)Slider設(shè)置Data Binding搔体。上一個(gè)Slider和Label的示例可以理解為Source影響Target恨樟,最簡(jiǎn)單的辦法就是可以使Source和Target相互影響。BindingMode枚舉可以幫助我們定義target 和 source之間的綁定模式疚俱。
BindingMode有四個(gè)枚舉值:
? Default
? OneWay — Source 的改變影響Target的值(通常是這種情況).
? OneWayToSource — Target的改變影響Source的值.
? TwoWay — Source和Target值改變會(huì)相互影響.

對(duì)于可讀寫的BindableProperty對(duì)象默認(rèn)BindingMode為OneWay劝术,只讀的BindableProperty對(duì)象默認(rèn)BindingMode為OneWayToSource。
大多數(shù)BindableProperty對(duì)象BindingMode默認(rèn)值為OneWay呆奕,以下控件的Property的BindingMode方式默認(rèn)是TwoWay:

由于Slider的Value默認(rèn)BindingMode為TwoWay养晋,所以實(shí)現(xiàn)兩個(gè)Slider連動(dòng)XAMlL定義為:

<StackLayout>
    <Slider x:Name="slider" VerticalOptions="CenterAndExpand" />
    <Slider BindingContext="{x:Reference Name=slider}" Value="{Binding Path=Value}" VerticalOptions="CenterAndExpand" />
</StackLayout>

通過(guò)XAML明確指定BindingMode的值Value="{Binding Path=Value Mode=TwoWay}"。通過(guò)C#代碼指定BindingMode的值slider.SetBinding(Slider.ValueProperty,"Value",BindingMode.TwoWay);梁钾。


Binding StringFormat 介紹

再次把Slider作為Source绳泉,Label作為Target。將Slider的Value值綁定到Label的Text姆泻。Value值ToString后直接顯示到Label上可能不是我們期望的零酪,Binding類提供了StringFormat屬性表示.NET格式化字符串冒嫡。

StringFormat效果

XAML中StringFormat使用,因?yàn)镾tringFormat本身會(huì)包含一對(duì)大括號(hào),所以StringFormat賦值時(shí)要包含一對(duì)單引號(hào):

C#代碼設(shè)置StringFormat:

label.SetBinding(Label.TextProperty, "Value", stringFormat: "Slider Value Is {0:F3}");

Binding IValueConvert 介紹

目前示例Target需要的數(shù)據(jù)為string四苇,默認(rèn)轉(zhuǎn)換或StringFormat可以實(shí)現(xiàn)效果灯谣。但是Data Binding的Target接受數(shù)據(jù)類型為一個(gè)對(duì)象時(shí)如何處理?我們可以通過(guò)value converter類完成Source到Target的類型轉(zhuǎn)換蛔琅,需要實(shí)現(xiàn)IValueConverter接口,接口有ConvertConvertBack兩個(gè)方法峻呛。

IValueConverter定義

當(dāng)數(shù)據(jù)由Source轉(zhuǎn)換到Target時(shí)調(diào)用Convert方法罗售。Convert方法中value表示Source傳遞的值,你可以通過(guò)GetType來(lái)確定它的類型钩述,也可以默認(rèn)一種類型來(lái)處理寨躁。targetType表示Target需要的數(shù)據(jù)類型,Convert方法返回的類型應(yīng)與targetType相同牙勘。parameter在Binding 中會(huì)用到职恳,culture為CultureInfo類型需要和地域文化相關(guān)的轉(zhuǎn)換時(shí)會(huì)用到。

ConvertBack方法會(huì)在數(shù)據(jù)由Target轉(zhuǎn)換到Source 時(shí)調(diào)用方面,只有Binding Mode為TwoWay 或者 OneWayToSource時(shí)才有必要實(shí)現(xiàn)該方法放钦,否則直接返回null即可。value參數(shù)表示target傳遞的值恭金,targetType表示source的Type類型操禀。

示例實(shí)現(xiàn)效果,一個(gè)Entry 和一個(gè)Button横腿,當(dāng)Entry中內(nèi)容為空時(shí)Button不可用颓屑,點(diǎn)擊Button清空Entry。

定義IntToBoolConverter實(shí)現(xiàn)IValueConverter耿焊,本示例中Entry為Source揪惦,Entry的Text.Length為Path,Button為Target罗侯,IsEnabled為綁定的屬性器腋。所以自定義的Converter應(yīng)有Int轉(zhuǎn)換為bool的能力(Convert方法,本例中ConvertBack可直接返回null)钩杰。

IntToBoolConverter類定義

XAML中使用Converter要先在Resources字典中定義IntToBoolConverter對(duì)象蒂培,指定key值,在Binding時(shí)通過(guò)StaticResource賦值榜苫。其中Resources相關(guān)內(nèi)容在Style中介紹护戳。

XAML使用IValueConverter

如果Converter只使用一次,不必在Resources中定義垂睬,直接在Binding中通過(guò)屬性節(jié)點(diǎn)定義即可媳荒。


《Creating Mobile Apps with Xamarin.Forms》中提供了一個(gè)bool轉(zhuǎn)泛型的Converter類抗悍,可以將bool值轉(zhuǎn)換為我們想要的值。定義如下:

BoolToObjectConverter定義

在XAML定義時(shí)钳枕,通過(guò) x:TypeArguments指定我們需要的類型缴渊,并設(shè)置TrueObject和FalseObject屬性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鱼炒,一起剝皮案震驚了整個(gè)濱河市衔沼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌昔瞧,老刑警劉巖指蚁,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異自晰,居然都是意外死亡凝化,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門酬荞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)搓劫,“玉大人,你說(shuō)我怎么就攤上這事混巧∏瓜颍” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵咧党,是天一觀的道長(zhǎng)遣疯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)凿傅,這世上最難降的妖魔是什么缠犀? 我笑而不...
    開(kāi)封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮聪舒,結(jié)果婚禮上辨液,老公的妹妹穿的比我還像新娘。我一直安慰自己箱残,他們只是感情好滔迈,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著被辑,像睡著了一般燎悍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盼理,一...
    開(kāi)封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天谈山,我揣著相機(jī)與錄音,去河邊找鬼宏怔。 笑死奏路,一個(gè)胖子當(dāng)著我的面吹牛畴椰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鸽粉,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼斜脂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了触机?” 一聲冷哼從身側(cè)響起帚戳,我...
    開(kāi)封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎儡首,沒(méi)想到半個(gè)月后片任,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡椒舵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了约谈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笔宿。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖棱诱,靈堂內(nèi)的尸體忽然破棺而出泼橘,到底是詐尸還是另有隱情,我是刑警寧澤迈勋,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布炬灭,位于F島的核電站,受9級(jí)特大地震影響靡菇,放射性物質(zhì)發(fā)生泄漏重归。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一厦凤、第九天 我趴在偏房一處隱蔽的房頂上張望鼻吮。 院中可真熱鬧,春花似錦较鼓、人聲如沸椎木。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)香椎。三九已至,卻和暖如春禽篱,著一層夾襖步出監(jiān)牢的瞬間畜伐,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工躺率, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留烤礁,地道東北人讼积。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像脚仔,于是被迫代替她去往敵國(guó)和親勤众。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

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