數(shù)據(jù)綁定介紹

2018-08-12 21:55 更新

數(shù)據(jù)綁定介紹

簡(jiǎn)單的數(shù)據(jù)綁定示例

相比于理論,我更傾向于從實(shí)踐中開始,尤其是對(duì)于數(shù)據(jù)綁定。那么,我們先來(lái)看看幾個(gè)簡(jiǎn)單的例子。

數(shù)據(jù)綁定到 TextBox

我們依舊使用前面的鬧鐘類來(lái)開始。在下面的代碼中,我們有屬性、構(gòu)造函數(shù),還有一個(gè) ToString() 方法的重載。之所以重載這個(gè)方法是因?yàn)槲覀兿朐谧詈蠼壎ǖ臅r(shí)候,這三個(gè)屬性能夠在 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;
        }
    }

接下來(lái)再在 XAML 中添加 TextBox 控件如下,因?yàn)?TextBox 此時(shí)是用作顯示而非輸入,所以建議設(shè)置其的只讀屬性。數(shù)據(jù)綁定的核心就是 Text 屬性中的那么一個(gè) Binding 關(guān)鍵字。

<TextBox x:Name="textBox1" FontSize="28" Height="150" Width="400"
                    TextWrapping="Wrap" Text="{Binding}" IsReadOnly="True"/>

但是光這樣還不夠,我們還需要在后臺(tái)代碼中將數(shù)據(jù)綁定到 textBox1 的 DataContext(數(shù)據(jù)上下文)中。

textBox1.DataContext = new Alarm(
                "First Alarm", "I need to study!", new DateTime(2015, 4, 11));

相信大家并不為覺得這個(gè)很難,相反我在學(xué)數(shù)據(jù)綁定的時(shí)候一上來(lái)就是一大堆理論,以至于我對(duì)數(shù)據(jù)一詞有了陰影——所以我學(xué)數(shù)據(jù)結(jié)構(gòu)非常痛苦。

數(shù)據(jù)綁定到 ComboBox

才保存一個(gè)鬧鐘沒太大意思,我們多來(lái)幾個(gè)。

        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ù)綁定提供了一個(gè)集合,這是因?yàn)樗鼘?shí)現(xiàn)了 INotifyPropertyChanged 和 INotifyCollectionChanged 接口。顧名思義,當(dāng)屬性改變時(shí),它可以通知它所綁定的控件,并且如果你希望該空間能夠同步更新,則將用于綁定的對(duì)象也實(shí)現(xiàn) INotifyPropertyChanged 接口。這個(gè)類好歸好,但相對(duì)于 TextBox 而言算有些高端了,以至于它無(wú)法顯示出來(lái)。但是我們可以用 ComboBox 來(lái)代替它,我們的類并不需要修改,前面的 UsefulAlarm 實(shí)例化也都不用改,只需要將 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 兩個(gè)控件的 Width 屬性的應(yīng)用區(qū)別。在 TextBox 中,我們將數(shù)據(jù)綁定到 Text 中;而在 ComboBox 中,我們則是將數(shù)據(jù)綁定到 ItemsSource 中,簡(jiǎn)單的說就是 ComboBox 拿來(lái)所有的數(shù)據(jù),再將它們分成小的細(xì)節(jié)發(fā)給它的子對(duì)象,這些子對(duì)象都在 ComboBox 的 DataTemplate(數(shù)據(jù)容器)中。

在這里我們并沒有用到前面所重載的 ToString() 函數(shù),因?yàn)槲覀円呀?jīng)分別將 Title、Description、AlarmTime 綁定到相應(yīng)的 TextBox 控件了。那圖示中又為什么這些數(shù)據(jù)都是一行一行的表示呢,這都是布局控件 StackPanel 的功勞,全靠它的Orientation屬性。如果將這個(gè)屬性設(shè)置成 Horizontal 呢,那標(biāo)題、描述已經(jīng)時(shí)間就是全排在一行了。

數(shù)據(jù)綁定到 ListBox

聽說 ListBox 和 ComboBox 很類似哦,它們都是 Box……XBox 呀。博主我有點(diǎn)懶,那可不可以直接將 ComboBox 的名字改成 ListBox 就直接運(yùn)行呢,答案是可以哦!那么區(qū)別到底在哪里呢?看看這張圖就知道啦。

咦?怎么只有一條鬧鐘了?別驚慌……拖動(dòng)右邊的滾動(dòng)條就可以查看到全部的鬧鐘咯。我真的只把 ComboBox 改成 ListBox 還有相應(yīng)的 Name 屬性(包括后臺(tái)代碼中的名字哦),以下就是完整的代碼啦,我會(huì)騙你?

        <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>

數(shù)據(jù)綁定到 ListView

看了前面的代碼相信我沒有騙你吧,童鞋們看到 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>

當(dāng)然了,還是用右邊的滾動(dòng)條來(lái)下拉以查看所有的數(shù)據(jù)。不過 ListView 君的最佳姿勢(shì)不是這樣哦,將 Height 改為 600 才是呢??聪聢D——這才是高大上的 ListView 君嘛!

好了不玩了,GridView 也是可以這樣弄得,不信你試試。

再談數(shù)據(jù)綁定

1.我們?yōu)槭裁匆脭?shù)據(jù)綁定

很顯然,我們不可能把所有的數(shù)據(jù)全部固定在特定的控件上。比如,游戲的積分、設(shè)定的鬧鐘、天氣預(yù)報(bào)甚至的通訊類的消息,它們都并非是一成不變的。但是也并非所有的控件都需要綁定,比如你的 App 的名字、發(fā)送消息時(shí)所用的發(fā)送按鈕上面的文本等。

2.那數(shù)據(jù)和 UI 之間又有哪些關(guān)系呢

首先我們得明確,數(shù)據(jù)的顯示和其后臺(tái)的管理是不一樣的。數(shù)據(jù)與UI綁定之后,我們的數(shù)據(jù)就可以在這兩者之間進(jìn)行溝通,如果數(shù)據(jù)發(fā)生變化時(shí),綁定到數(shù)據(jù)的 UI 則會(huì)自動(dòng)將相應(yīng)的屬性進(jìn)行調(diào)整,不僅僅是前面用到的 Text 屬性,還有 FontSize、Width、Foreground、Image 屬性都可以。

3.數(shù)據(jù)綁定到底是綁定什么

首先,我們得有綁定源,這些就是我們需要綁定的數(shù)據(jù),沒有數(shù)據(jù),即使你綁定了,它也顯示不出來(lái)。 其次,我們還需要綁定目標(biāo),也就是 Framework 類的 DependencyProperty 屬性,說得白話文點(diǎn)就是將數(shù)據(jù)綁定到 UI 的相應(yīng)屬性上。

最后,我們還需要一個(gè) Binding 對(duì)象,它就像是搬運(yùn)工,沒有它,數(shù)據(jù)也是無(wú)法動(dòng)彈的。它能夠幫助我們將數(shù)據(jù)從數(shù)據(jù)源移動(dòng)到綁定目標(biāo),并且將綁定目標(biāo)的相應(yīng)消息通知給綁定源。它還有一些巧妙的工具,能夠?qū)⒔壎ㄔ吹臄?shù)據(jù)加工成特定的格式。

4.綁定源有哪些

所有的公共語(yǔ)言運(yùn)行時(shí)對(duì)象,我們前面用的Alarm類就是這種對(duì)象,另外UI元素也是哦。

5.聽說有的搬運(yùn)工只能將數(shù)據(jù)源的數(shù)據(jù)一次性搬到綁定目標(biāo)后就不再搬了,而有的搬運(yùn)工則會(huì)在數(shù)據(jù)修改后再搬一次,甚至還有的能夠在綁定目標(biāo)更改后再將數(shù)據(jù)搬回到數(shù)據(jù)源

  • OneTime 綁定:這個(gè)搬運(yùn)工的工作就是第一種,它只負(fù)責(zé)在創(chuàng)建時(shí)將源數(shù)據(jù)更新到綁定目標(biāo)。
  • OneWay 綁定:這是系統(tǒng)默認(rèn)的搬運(yùn)工,它是第二種,負(fù)責(zé)在創(chuàng)建時(shí)以及源數(shù)據(jù)發(fā)生更改時(shí)更新綁定目標(biāo)。
  • TwoWay 綁定:這個(gè)搬運(yùn)工則是第三種,它能夠在綁定源和綁定目標(biāo)的一邊發(fā)生更改時(shí)同時(shí)更新綁定源和綁定目標(biāo)。但它在一種時(shí)候卻會(huì)偷懶,那就是對(duì)于TextBox.Text每次點(diǎn)擊之后,它就不會(huì)將這個(gè) Text 屬性的更改更新到綁定源。不過如果碰到 Boss,它也只能繼續(xù)搬了。那就是將 Binding.UpdateSourceTrigger 設(shè)置成PropertyChanged。而默認(rèn)情況下,只有 TextBox 失去焦點(diǎn)時(shí)才會(huì)去更新。

以下分別是 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>

拖動(dòng)滑動(dòng)條,就可以看到在 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>

如下圖所示,點(diǎn)擊 Item 1 后 TextBox 則會(huì)顯示相應(yīng)的 Item 1,將 TextBox 中的 Item 1 修改為 Item 5 后再 ListBox 中也自動(dòng)修改成了 Item5。

簡(jiǎn)單示例:Foreground 的數(shù)據(jù)綁定

前面已經(jīng)說到了 Foreground 也可以綁定,想不想試試呢。我們現(xiàn)在 TextBox 中寫一個(gè) TextBox,然后在后臺(tái)代碼中添加一個(gè)綁定就可以了。這個(gè)和前面的比較簡(jiǎn)單,這里只是用來(lái)引出后面的東東哦

 <TextBox Name="textBox" Width="200" Height="100" IsReadOnly="True"
                 FontSize="32" Text="Text" Foreground="{Binding ForeBrush}"/>
textBox.Foreground = new SolidColorBrush(Colors.BlueViolet);
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)