標籤:
資料繫結的意義?
能夠降低後台擷取資料與XAML展示頁面元素兩者間的耦合度。
資料繫結有好多種形式,接下來一一陳述。
Demo One
首先做一個單一資料的綁定:在後台定義一個公用層級的自動屬性,然後再XAML初始化語句執行前對該屬性賦值,XAML初始化執行後,將當前資料放到資料內容中,然後在前台頁面就可以通過資料繫結拿到當前資料,具體代碼如下:
1 public DateTime Time { get; set; }2 public MainPage()3 {4 //初始化資料5 Time = DateTime.Now; 6 this.InitializeComponent();7 //一定要把資料繫結放在XAML初始化後面8 this.DataContext = Data;9 }
前台代碼:
<TextBox x:Name="txt" Text="{Binding}" />
啟動調試,我們就可以看到目前時間被綁定到了TextBox上。如果我現在有很多屬性要綁定到前台元素上怎麼辦?
Demo Two
首先建一個ViewModel類,用來定義各種展示用的屬性,假如我們前台需要展示人的各種資訊,包括姓名、年齡、身高,首先定義一個PersonViewModel類(這是一個資料來源),
1 public class PersonViewModel2 {//Person資料來源3 public string Name { get; set; }4 public int Age { get; set; }5 public float Height { get; set; }6 }
然後定義一個用於接受資料的屬性,
public PersonViewModel PersonData { get; set; }
然後在建構函式中進行初始化,
1 //初始化資料2 PersonData = new PersonViewModel { Name = "萵苣的宅森", Age = 24, Height = 175 };3 this.InitializeComponent();4 //將資料繫結到資料內容 一定要放到XAML初始化語句後面5 this.DataContext = PersonData;
最後在前台進行資料繫結,
1 <StackPanel>2 <TextBox x:Name="txtname" Header="姓名" Text="{Binding Name}"/>3 <!—這裡的{Binding Name} 相當於{Binding Path=Name}-->4 <TextBox x:Name="txtAge" Header="年齡" Text="{Binding Age}"/>5 <!—假如Binding的屬性下面還有子屬性(也就是說綁定了一個class)那麼想拿到該屬性下面的屬性就可以用”.”點出來-->6 <TextBox x:Name="txtHeight" Header="身高" Text="{Binding Height}"/>7 <!—假如Binding的屬性是一個集合,那麼也可以使用索引器的形式 屬性[index] 進行資料繫結-->8 </StackPanel>
運行結果如:
以上兩個Demo都是通過後台賦值的形式把資料賦給了資料內容DataContext,我們還可以在前台頁面通過DataContext屬性進行資料繫結。
Demo Three
將背景
this.DataContext = PersonData;
語句注釋掉,這個時進行調試Person的資訊肯定是不會顯示的,因為我們前台綁定資料需要從資料內容DataContext拿到資料,這時候我們在Page節下增加一個DataContext屬性
DataContext="{Binding PersonData,RelativeSource={RelativeSource Mode=Self}
,就可以以屬性的形式給DataContext賦值,如果想要檢驗資料來源是否正確,只需要在PersonData上按F12轉到定義,如果轉到的是後台資料來源對應的自動屬性
public PersonViewModel PersonData { get; set; }
,那麼就說明DataContext成功賦值。用前台屬性的方式綁定DataContext資料內容要注意:在後台一定要先初始化資料,然後再初始化XAML,你想啊,XAML都初始化完了你再給DataContext賦值,是不是晚了。。
通過這種形式對資料進行綁定就可以完全將前後台分離開,我在後台只需要設定一下資料來源,然後資料繫結的工作完全都在前台進行,不管前台元素是TextBox還是其他的控制項都與後台沒有關係。這樣去開發代碼分工明確,靈活性也高。
到這裡你有沒有產生一個疑問,我把DataContext藝術性的形式設定在Page節為什麼 Page節下面的元素也能夠綁定到資料?這是因為資料內容DataContext是可以繼承的,只要父級元素設定了資料內容,其子級元素都能夠使用這資料內容,當然自己元素也可以綁定自己的或者重寫父級的DataContext(DataContext有個就近原則)。
上面講的都是使用自訂資料來源進行資料的綁定,我們還可以使用UI元素進行資料繫結,這樣還可以實現兩個UI元素之間的互動。
Demo Four
1 <StackPanel>2 <Slider x:Name="slider" Minimum="0" Maximum="100" Value="10"/>3 <Rectangle Width="{Binding ElementName=slider,Path=Value}" Height="{Binding ElementName=slider,Path=Value}" Fill="Green"/>4 </StackPanel>
定義一個Slider滑動條,通過滑塊來控制矩形的大小,只需要綁定Rectangle的Width和Height屬性,為ElementName 賦予控制者的Name,Path賦予控制者的值變化屬性,即可與被控制者綁定起來,實現互動。
當資料來源和目標屬性的類型不相同時,例如前台需要一個string類型的資料,而我現在拿到的是一個int類型的資料,這時候就需要類型轉換。要實作類別型轉換,可以建立一個轉換工廠,他必須實現IValueConverter介面,在Convert方法下可以編寫轉換用的代碼(ConvertBack也是用來編寫目標資料的方法,這個方式是適用TwoWay繫結模式的)。
這裡又談到了繫結模式,上面幾個Demo用的繫結模式都是Default即預設繫結模式,繫結模式還有OneTime、OneWay、TwoWay三種模式,下面用一個Demo解釋這三種繫結模式的區別。
Demo Five
當我們滑動滑塊,會發現只有OneTime的值是不變化的,Slider一開始設定的值是多少他就是多少,而在TwoWay的文字框中輸入一個值會導致Slider、Normal、OneWay的值同樣也發生變化。
前台源碼:
1 <Grid x:Name="LayoutRoot"> 2 3 <Grid.RowDefinitions> 4 <RowDefinition Height="Auto"/> 5 <RowDefinition Height="*"/> 6 </Grid.RowDefinitions> 7 8 <!-- 標題面板 --> 9 <StackPanel Grid.Row="0" Margin="19,0,0,0">10 <TextBlock Text="繫結模式" Style="{ThemeResource TitleTextBlockStyle}" Margin="0,12,0,0"/>11 <TextBlock Text="繫結模式" Margin="0,-6.5,0,26.5" Style="{ThemeResource HeaderTextBlockStyle}" CharacterSpacing="{ThemeResource PivotHeaderItemCharacterSpacing}"/>12 </StackPanel>13 14 <!--TODO: 應將內容放入以下網格-->15 <StackPanel Grid.Row="1" x:Name="ContentRoot" Margin="19,9.5,19,0">16 <Slider x:Name="slider" Header="資料來源" Grid.Row="0"/>17 <TextBox Header="Normal" Text="{Binding ElementName=slider,Path=Value}"/>18 <TextBox Header="OneTime" Text="{Binding ElementName=slider,Path=Value,Mode=OneTime}"/>19 <TextBox Header="OneWay" Text="{Binding ElementName=slider,Path=Value,Mode=OneWay}"/>20 <TextBox Header="TwoWay" Text="{Binding ElementName=slider,Path=Value,Mode=TwoWay}"/>21 </StackPanel>22 </Grid>
Windows Phone 8.1 資料繫結