本文爲系列文章第十一篇,主要介紹Silverlight 2中的數據綁定。
在Silverlight 2中,支持三種模式的數據綁定。
1.OneTime:一次綁定,在綁定創建時使用源數據更新目標,適用於只顯示數據而不進行數據的更新。
2.OneWay:單向綁定,在綁定創建時或者源數據發生變化時更新到目標,適用於顯示變化的數據。
3.TwoWay:雙向綁定,在任何時候都可以同時更新源數據和目標。
Jesse Liberty舉的例子非常的形象,使用Silverlight開發一個在線書店,顯示書籍的書名、作者等信息,使用OneTime模式,這些數據一般不會發生變化的;顯示價格信息時使用OneWay模式,因爲管理員可能會在一天內調整價格;顯示書籍的剩餘數量時用TwoWay模式,數量隨着用戶的訂購會隨時發生變化,即目標和源數據都要進行更新。
在本示例中我們將做一個簡單的數據綁定,用來顯示用戶信息,XAML如下:
<Grid x:Name="LayoutRoot" Background="#46461F"> <Grid.RowDefinitions> <RowDefinition Height="160"></RowDefinition> <RowDefinition Height="40"></RowDefinition> <RowDefinition Height="40"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="150"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <Image Source="terrylee.jpg" Width="78" Height="100" HorizontalAlignment="Left" Grid.Row="0" Grid.Column="1"/> <TextBlock Foreground="White" FontSize="18" Text="姓名:" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right"/> <TextBlock x:Name="lblName" Foreground="White" FontSize="18" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left"/> <TextBlock Foreground="White" FontSize="18" Text="位置:" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Right"/> <TextBlock x:Name="lblAddress" Foreground="White" FontSize="18" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Left"/> </Grid>
添加一個簡單User類,它具有Name和Address兩個屬性:
public class User { public string Name { get; set; } public string Address { get; set; } }
使用綁定句法{Binding Property}進行數據綁定,注意下面的兩個TextBlock控件Text屬性:
<Grid x:Name="LayoutRoot" Background="#46461F"> <Grid.RowDefinitions> <RowDefinition Height="160"></RowDefinition> <RowDefinition Height="40"></RowDefinition> <RowDefinition Height="40"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="150"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <Image Source="terrylee.jpg" Width="78" Height="100" HorizontalAlignment="Left" Grid.Row="0" Grid.Column="1"/> <TextBlock Foreground="White" FontSize="18" Text="姓名:" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right"/> <TextBlock x:Name="lblName" Foreground="White" FontSize="18" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Text="{Binding Name}"/> <TextBlock Foreground="White" FontSize="18" Text="位置:" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Right"/> <TextBlock x:Name="lblAddress" Foreground="White" FontSize="18" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Left" Text="{Binding Address}"/> </Grid>
指定數據源,注意這裏是創建一個User的實例並賦值後,把user實例綁定到了TextBlock的DataContext上,而不是向之前我們所做的示例中那樣,直接指定Text屬性:
private void UserControl_Loaded(object sender, RoutedEventArgs e) { User user = new User(); user.Name = "TerryLee"; user.Address = "中國 天津"; lblName.DataContext = user; lblAddress.DataContext = user; }
運行示例後,可以看到:
上面這種數據綁定模式,只是顯示數據而不對數據做任何修改,默認的綁定模式是一次綁定OneTime。
如果需要在數據源發生變化時能夠通知UI進行相應的更新,即使用單向綁定OneWay或者雙向綁定TwoWay,則業務實體需要實現接口INotifyPropertyChanged。在本示例中,我們加上一個更新按鈕,當單擊按鈕時更新user實例的屬性值,會看到界面上的數據也會發生變化。
修改一下User類,使其實現INotifyPropertyChanged接口。
public class User : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private string _name; public string Name { get { return _name; } set { _name = value; if(PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("Name")); } } } private string _address; public string Address { get { return _address; } set { _address = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("Address")); } } } }
修改數據綁定模式,使用單向綁定OneWay模式,如{Binding Address, Mode=OneWay}
<Grid x:Name="LayoutRoot" Background="#46461F"> <Grid.RowDefinitions> <RowDefinition Height="160"></RowDefinition> <RowDefinition Height="40"></RowDefinition> <RowDefinition Height="40"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="150"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <Image Source="terrylee.jpg" Width="78" Height="100" HorizontalAlignment="Left" Grid.Row="0" Grid.Column="1"/> <Button x:Name="btnUpdate" Width="100" Height="40" Content="Update" Click="btnUpdate_Click"/> <TextBlock Foreground="White" FontSize="18" Text="姓名:" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right"/> <TextBlock x:Name="lblName" Foreground="White" FontSize="18" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Text="{Binding Name, Mode=OneWay}"/> <TextBlock Foreground="White" FontSize="18" Text="位置:" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Right"/> <TextBlock x:Name="lblAddress" Foreground="White" FontSize="18" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Left" Text="{Binding Address, Mode=OneWay}"/> </Grid>
編寫事件處理程序,爲了演示把user聲明爲一個全局的,並在按鈕的單擊事件中修改其屬性值:
public partial class Page : UserControl { public Page() { InitializeComponent(); } User user; private void UserControl_Loaded(object sender, RoutedEventArgs e) { user = new User(); user.Name = "TerryLee"; user.Address = "中國 天津"; lblName.DataContext = user; lblAddress.DataContext = user; } private void btnUpdate_Click(object sender, RoutedEventArgs e) { user.Name = "李會軍"; user.Address = "China Tianjin"; } }
運行後如下所示:
單擊Update按鈕後:
下面再看一個綁定到列表的簡單例子,一般都會使用DataGrid或者ListBox來進行列表數據的顯示。下面的示例我們顯示一個文章列表:
<Grid Background="#46461F"> <Grid.RowDefinitions> <RowDefinition Height="40"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Border Grid.Row="0" Grid.Column="0" CornerRadius="15" Width="240" Height="36" Background="Orange" Margin="20 0 0 0" HorizontalAlignment="Left"> <TextBlock Text="文章列表" Foreground="White" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20 0 0 0"></TextBlock> </Border> <ListBox x:Name="PostList" Grid.Column="0" Grid.Row="1" Margin="40 10 10 10" HorizontalContentAlignment="Left" VerticalContentAlignment="Bottom" ItemsSource="{Binding Posts}"> </ListBox> </Grid>
public class Blog { public List<String> Posts { get; set; } }
private void UserControl_Loaded(object sender, RoutedEventArgs e) { Blog blog = new Blog(); blog.Posts = new List<String> { "一步一步學Silverlight 2系列(10):使用用戶控件", "一步一步學Silverlight 2系列(9):使用控件模板", "一步一步學Silverlight 2系列(8):使用樣式封裝控件觀感", "一步一步學Silverlight 2系列(7):全屏模式支持" }; PostList.DataContext = blog; }
最終運行的結果如下所示:
當然我們也可以使用ListBox的ItemsSource屬性進行綁定,
本文簡單介紹了Silverlight 2中的數據綁定,你可以從這裏下載文章示例代碼。