相比于理論,我更傾向于從實踐中開始,尤其是對于數(shù)據(jù)綁定。那么,我們先來看看幾個簡單的例子。
我們依舊使用前面的鬧鐘類來開始。在下面的代碼中,我們有屬性、構(gòu)造函數(shù),還有一個 ToString() 方法的重載。之所以重載這個方法是因為我們想在最后綁定的時候,這三個屬性能夠在 TextBox 上顯示得更加工整。
public class Alarm
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime AlarmTime { get; set; }
public Alarm() { }
public Alarm(string title, string description,DateTime alarmTime)
{
Title = title;
Description = description;
AlarmTime = alarmTime;
}
public override string ToString()
{
return "Title: " + Title +"\n"+ "Time: "+ AlarmTime.ToString("d") + "\n"+ "Description: " + Description;
}
}
接下來再在 XAML 中添加 TextBox 控件如下,因為 TextBox 此時是用作顯示而非輸入,所以建議設置其的只讀屬性。數(shù)據(jù)綁定的核心就是 Text 屬性中的那么一個 Binding 關(guān)鍵字。
<TextBox x:Name="textBox1" FontSize="28" Height="150" Width="400"
TextWrapping="Wrap" Text="{Binding}" IsReadOnly="True"/>
但是光這樣還不夠,我們還需要在后臺代碼中將數(shù)據(jù)綁定到 textBox1 的 DataContext(數(shù)據(jù)上下文)中。
textBox1.DataContext = new Alarm(
"First Alarm", "I need to study!", new DateTime(2015, 4, 11));
相信大家并不為覺得這個很難,相反我在學數(shù)據(jù)綁定的時候一上來就是一大堆理論,以至于我對數(shù)據(jù)一詞有了陰影——所以我學數(shù)據(jù)結(jié)構(gòu)非常痛苦。
才保存一個鬧鐘沒太大意思,我們多來幾個。
public ObservableCollection<Alarm> UsefulAlarm = new ObservableCollection<Alarm>();
public MainPage()
{
this.InitializeComponent();
UsefulAlarm.Add(new Alarm("First Alarm", "I need to study!", new DateTime(2015, 4, 11)));
UsefulAlarm.Add(new Alarm("First Alarm", "Read a magzine!", new DateTime(2015, 4, 12)));
UsefulAlarm.Add(new Alarm("First Alarm", "Write a blog!", new DateTime(2015, 4, 15)));
UsefulAlarm.Add(new Alarm("First Alarm", "Travel", new DateTime(2015, 5, 15)));
textBox1.DataContext = UsefulAlarm;
}
但是……
很顯然我們用了 ObservableCollection< T >
類,它為數(shù)據(jù)綁定提供了一個集合,這是因為它實現(xiàn)了 INotifyPropertyChanged 和 INotifyCollectionChanged 接口。顧名思義,當屬性改變時,它可以通知它所綁定的控件,并且如果你希望該空間能夠同步更新,則將用于綁定的對象也實現(xiàn) INotifyPropertyChanged 接口。這個類好歸好,但相對于 TextBox 而言算有些高端了,以至于它無法顯示出來。但是我們可以用 ComboBox 來代替它,我們的類并不需要修改,前面的 UsefulAlarm 實例化也都不用改,只需要將 textBox1 改成 comboBox1 即可。以下是新的 ComboBox 代碼。
<ComboBox Name="comboBox1" ItemsSource="{Binding}" FontSize="28" Height="150" Width="400">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="8">
<TextBox Width="350" TextWrapping="Wrap" Text="{Binding Title}" IsReadOnly="True"/>
<TextBox Width="350" TextWrapping="Wrap" Text="{Binding Description}" IsReadOnly="True"/>
<TextBox Width="350" TextWrapping="Wrap" Text="{Binding AlarmTime}" IsReadOnly="True"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
在圖示中我們也容易發(fā)現(xiàn) TextBox 和 ComboBox 兩個控件的 Width 屬性的應用區(qū)別。在 TextBox 中,我們將數(shù)據(jù)綁定到 Text 中;而在 ComboBox 中,我們則是將數(shù)據(jù)綁定到 ItemsSource 中,簡單的說就是 ComboBox 拿來所有的數(shù)據(jù),再將它們分成小的細節(jié)發(fā)給它的子對象,這些子對象都在 ComboBox 的 DataTemplate(數(shù)據(jù)容器)中。
在這里我們并沒有用到前面所重載的 ToString() 函數(shù),因為我們已經(jīng)分別將 Title、Description、AlarmTime 綁定到相應的 TextBox 控件了。那圖示中又為什么這些數(shù)據(jù)都是一行一行的表示呢,這都是布局控件 StackPanel 的功勞,全靠它的Orientation屬性。如果將這個屬性設置成 Horizontal 呢,那標題、描述已經(jīng)時間就是全排在一行了。
聽說 ListBox 和 ComboBox 很類似哦,它們都是 Box……XBox 呀。博主我有點懶,那可不可以直接將 ComboBox 的名字改成 ListBox 就直接運行呢,答案是可以哦!那么區(qū)別到底在哪里呢?看看這張圖就知道啦。
咦?怎么只有一條鬧鐘了?別驚慌……拖動右邊的滾動條就可以查看到全部的鬧鐘咯。我真的只把 ComboBox 改成 ListBox 還有相應的 Name 屬性(包括后臺代碼中的名字哦),以下就是完整的代碼啦,我會騙你?
<ListBox Name="listBox1" ItemsSource="{Binding}" FontSize="28" Height="150" Width="400">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="8">
<TextBox Width="350" TextWrapping="Wrap" Text="{Binding Title}" IsReadOnly="True"/>
<TextBox Width="350" TextWrapping="Wrap" Text="{Binding Description}" IsReadOnly="True"/>
<TextBox Width="350" TextWrapping="Wrap" Text="{Binding AlarmTime}" IsReadOnly="True"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
看了前面的代碼相信我沒有騙你吧,童鞋們看到 ListBox 有沒有想到 ListView 呢?我要是想說還是和前面一樣只用改名字等就可以用 ListView,你還是不信么?
<ListView Name="listView1" ItemsSource="{Binding}" FontSize="28" Height="150" Width="400">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="8">
<TextBox Width="350" TextWrapping="Wrap" Text="{Binding Title}" IsReadOnly="True"/>
<TextBox Width="350" TextWrapping="Wrap" Text="{Binding Description}" IsReadOnly="True"/>
<TextBox Width="350" TextWrapping="Wrap" Text="{Binding AlarmTime}" IsReadOnly="True"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
當然了,還是用右邊的滾動條來下拉以查看所有的數(shù)據(jù)。不過 ListView 君的最佳姿勢不是這樣哦,將 Height 改為 600 才是呢??聪聢D——這才是高大上的 ListView 君嘛!
好了不玩了,GridView 也是可以這樣弄得,不信你試試。
1.我們?yōu)槭裁匆脭?shù)據(jù)綁定
很顯然,我們不可能把所有的數(shù)據(jù)全部固定在特定的控件上。比如,游戲的積分、設定的鬧鐘、天氣預報甚至的通訊類的消息,它們都并非是一成不變的。但是也并非所有的控件都需要綁定,比如你的 App 的名字、發(fā)送消息時所用的發(fā)送按鈕上面的文本等。
2.那數(shù)據(jù)和 UI 之間又有哪些關(guān)系呢
首先我們得明確,數(shù)據(jù)的顯示和其后臺的管理是不一樣的。數(shù)據(jù)與UI綁定之后,我們的數(shù)據(jù)就可以在這兩者之間進行溝通,如果數(shù)據(jù)發(fā)生變化時,綁定到數(shù)據(jù)的 UI 則會自動將相應的屬性進行調(diào)整,不僅僅是前面用到的 Text 屬性,還有 FontSize、Width、Foreground、Image 屬性都可以。
3.數(shù)據(jù)綁定到底是綁定什么
首先,我們得有綁定源,這些就是我們需要綁定的數(shù)據(jù),沒有數(shù)據(jù),即使你綁定了,它也顯示不出來。 其次,我們還需要綁定目標,也就是 Framework 類的 DependencyProperty 屬性,說得白話文點就是將數(shù)據(jù)綁定到 UI 的相應屬性上。
最后,我們還需要一個 Binding 對象,它就像是搬運工,沒有它,數(shù)據(jù)也是無法動彈的。它能夠幫助我們將數(shù)據(jù)從數(shù)據(jù)源移動到綁定目標,并且將綁定目標的相應消息通知給綁定源。它還有一些巧妙的工具,能夠?qū)⒔壎ㄔ吹臄?shù)據(jù)加工成特定的格式。
4.綁定源有哪些
所有的公共語言運行時對象,我們前面用的Alarm類就是這種對象,另外UI元素也是哦。
5.聽說有的搬運工只能將數(shù)據(jù)源的數(shù)據(jù)一次性搬到綁定目標后就不再搬了,而有的搬運工則會在數(shù)據(jù)修改后再搬一次,甚至還有的能夠在綁定目標更改后再將數(shù)據(jù)搬回到數(shù)據(jù)源
以下分別是 OneWay 和 TwoWay 的例子:
<StackPanel Width="240" Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<Slider Name="slider1" Minimum="0" Maximum="100"/>
<TextBox FontSize="30"
Text="{Binding ElementName=slider1,Path=Value,Mode=OneWay}" />
</StackPanel>
拖動滑動條,就可以看到在 TextBox 中顯示它的值的變化了。如果希望它只變化一次,那就將代碼中的 OneWay 改成 OneTime 即可。
<StackPanel Width="240" Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox FontSize="30" Name="textBox" Height="60"
Text ="{Binding ElementName=listBox1, Path=SelectedItem.Content, Mode=TwoWay}">
</TextBox>
<ListBox FontSize="30" Name="listBox1">
<ListBoxItem Content="Item 1"/>
<ListBoxItem Content="Item 2"/>
<ListBoxItem Content="Item 3"/>
<ListBoxItem Content="Item 4"/>
</ListBox>
</StackPanel>
如下圖所示,點擊 Item 1 后 TextBox 則會顯示相應的 Item 1,將 TextBox 中的 Item 1 修改為 Item 5 后再 ListBox 中也自動修改成了 Item5。
簡單示例:Foreground 的數(shù)據(jù)綁定
前面已經(jīng)說到了 Foreground 也可以綁定,想不想試試呢。我們現(xiàn)在 TextBox 中寫一個 TextBox,然后在后臺代碼中添加一個綁定就可以了。這個和前面的比較簡單,這里只是用來引出后面的東東哦
<TextBox Name="textBox" Width="200" Height="100" IsReadOnly="True"
FontSize="32" Text="Text" Foreground="{Binding ForeBrush}"/>
textBox.Foreground = new SolidColorBrush(Colors.BlueViolet);
更多建議: