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

2018-08-12 21:55 更新

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

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

相比于理論,我更傾向于從實踐中開始,尤其是對于數(shù)據(jù)綁定。那么,我們先來看看幾個簡單的例子。

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

我們依舊使用前面的鬧鐘類來開始。在下面的代碼中,我們有屬性、構(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)非常痛苦。

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

才保存一個鬧鐘沒太大意思,我們多來幾個。

        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)時間就是全排在一行了。

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

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

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

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

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

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

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ù)源

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

以下分別是 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);
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號