一步一步学Silverlight 2系列(11):数据绑定

概念

Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, Ironpython,对JSON、Web Service、WCF以及Sockets的支持等一系列新的特性。《一步一步学Silverlight 2系列》文章带您快速进入Silverlight 2开发。

本文为系列文章第十一篇,主要介绍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;
}

运行示例后,可以看到:

TerryLee_Silverlight2_0055

上面这种数据绑定模式,只是显示数据而不对数据做任何修改,默认的绑定模式是一次绑定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";
    }
}

运行后如下所示:

TerryLee_Silverlight2_0056

单击Update按钮后:

TerryLee_Silverlight2_0057

绑定到列表

下面再看一个绑定到列表的简单例子,一般都会使用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;
}

最终运行的结果如下所示:

TerryLee_Silverlight2_0058

当然我们也可以使用ListBox的ItemsSource属性进行绑定,

结束语

本文简单介绍了Silverlight 2中的数据绑定,你可以从这里下载文章示例代码。

下一篇:一步一步学Silverlight 2系列(12):数据与通信之WebClient

Tag标签: Silverlight

posted on 2008-03-08 23:48 TerryLee 阅读(4846) 评论(47)  编辑 收藏 所属分类: Silverlight

评论

#1楼  2008-03-09 01:12 Jacky_Xu      

辛苦了。已经写两天了!都有点跟不上了! :)   回复  引用  查看    

#2楼  2008-03-09 01:22 hxm      

http://silverlight.net/Learn/videocat.aspx?cat=2

how do i
silverlight 系列   回复  引用  查看    

#3楼  2008-03-09 06:47 过客007 [未注册用户]

请问博主能否简单的举一个用linq取数据,再绑定显示到网页的例子?   回复  引用  查看    

#4楼  2008-03-09 06:56 过客007 [未注册用户]

还有一个问题:看一些例子,好象一个silverlight应用最后只生成一个xap文件,是不是当需要多个xap文件时,需要在一个解决方案中建很多个项目?

对博主的劳动表示谢意.
  回复  引用  查看    

#5楼 [楼主] 2008-03-09 12:24 TerryLee      

@Jacky_Xu
呵呵,不辛苦:)   回复  引用  查看    

#6楼 [楼主] 2008-03-09 12:24 TerryLee      

@hxm
:)   回复  引用  查看    

#7楼 [楼主] 2008-03-09 12:28 TerryLee      

@过客007
Silverlight不可以直接访问数据,你可以通过WCF、JSON、WebClient、WebRequest等方式取数据,并进行绑定,但是支持LINQ和LINQ to XML,后面会有相关的例子   回复  引用  查看    

#8楼 [楼主] 2008-03-09 12:29 TerryLee      

@过客007
现在看来只能这样去做,一个项目生成一个.xap文件   回复  引用  查看    

#9楼  2008-03-09 15:09 过客007 [未注册用户]

谢谢楼主回答.

并且非常高兴的看到楼主的另一篇文章也完成了.   回复  引用  查看    

#10楼 [楼主] 2008-03-09 15:18 TerryLee      

@过客007
不用客气^_^   回复  引用  查看    

#11楼  2008-03-10 22:09 守護~︶箬      

李老师,我调试的时候经常出现错误:文件“D:\Silverlight\ControlCustom\ControlCustom\ClientBin\ControlCustom.xap”正由另一进程使用,因此该进程无法访问该文件。

是哪个进程呢?   回复  引用  查看    

#12楼 [楼主] 2008-03-10 22:13 TerryLee      

@守護~︶箬
你把Web Development Server停止了,然后再调试,试试看   回复  引用  查看    

#13楼  2008-03-10 23:09 ArthurHend      

请问private void UserControl_Loaded()这个是写在哪个文件中的?   回复  引用  查看    

#14楼 [楼主] 2008-03-10 23:19 TerryLee      

@ArthurHend
Page.xaml.cs文件中的,可以下载示例代码看一下:)   回复  引用  查看    

#15楼  2008-03-10 23:27 ArthurHend      

@TerryLee
刚下来看过了!呵呵……我想问这个UserControl_Loaded是哪里自动生成的还是直接写的啊?   回复  引用  查看    

#16楼 [楼主] 2008-03-10 23:41 TerryLee      

在可以在XAML中编辑器中,未UserControl添加Loaded事件,按Tab键自动生成,也可以自己手动去写。可以看一下鼠标事件处理一文:
http://www.cnblogs.com/Terrylee/archive/2008/03/07/Silverlight2-step-by-step-part4-mouse-events-handle.html   回复  引用  查看    

#17楼  2008-03-12 22:15 高 [未注册用户]

为什么我调试的时候,以本地的形式可以看,但是以http的时候,都是显示不出来?
  回复  引用  查看    

#18楼 [楼主] 2008-03-13 12:58 TerryLee      

@高
可能是你的开发环境哪儿安装的有问题吧   回复  引用  查看    

#19楼  2008-03-13 20:17 Zhuang miao      

你写的比我看的还快!是人是神??   回复  引用  查看    

#20楼 [楼主] 2008-03-13 20:20 TerryLee      

@Zhuang miao
是人,呵呵:)   回复  引用  查看    

#21楼  2008-03-13 20:27 Zhuang miao      

@TerryLee
这两天一直在看你写的这个系列,真不错,就是看的有点慢~那个WCF是你翻译的吗?准备买本   回复  引用  查看    

#22楼 [楼主] 2008-03-13 20:35 TerryLee      

@Zhuang miao
不是,是张逸和徐宁翻译的:)   回复  引用  查看    

#23楼  2008-03-20 12:23 张荣华      

@TerryLee
UserControl_Loaded()方法是不是需要在Page()中调用一下啊?   回复  引用  查看    

#24楼 [楼主] 2008-03-20 12:54 TerryLee      

@张荣华
在XAML中声明就可以了...   回复  引用  查看    

#25楼  2008-04-16 10:38 qingquan126778 [未注册用户]

我在运行单向绑定示例时怎么出现了
“System.NullReferenceException”类型的异常 但未在用户代理码中进行处理
请问该如何解决呢?   回复  引用  查看    

#26楼  2008-04-19 11:34 yww      

Silverlight不可以直接访问数据,你可以通过WCF、JSON、WebClient、WebRequest等方式取数据,并进行绑定,但是支持LINQ和LINQ to XML,后面会有相关的例子
--这个后面的例子在哪里?

另外,习惯了DataGrid和GridView的asp.net developer, 似乎在这个grid和ListBox 的例子中中找不到Header,TemplateColumn等概念。如何绑定一个常见的数据表格呢?
  回复  引用  查看    

#27楼  2008-04-22 16:33 tiany [未注册用户]

能说一下类在silverlight中是怎么引用的吗?怎么在按钮单击事件不能创建类的实体?   回复  引用  查看    

#28楼  2008-05-18 01:50 xdpxdp [未注册用户]

看完基础系列,强悍,佩服啊,谢过   回复  引用  查看    

#29楼  2008-06-02 21:01 tthxnz      

请问绑定的时候如何写格式化字符串呢   回复  引用  查看    

#30楼  2008-06-16 14:17 libo [未注册用户]

错误 1 “SilverlightApplication9.User”不实现接口成员“System.ComponentModel.INotifyPropertyChanged.PropertyChanged” 是怎么回事呢?   回复  引用  查看    

#31楼  2008-06-18 16:31 numbmeteor [未注册用户]

看完了基礎部分了,雖然由於基礎差沒能看出個所以然來但我是一個字母一個字母敲到VS裡的總還是有不少收穫的,在此感謝您無私的付出,您辛苦了。   回复  引用  查看    

#32楼  2008-06-18 20:58 EdisonDu [未注册用户]

@libo
我粗心的遇到你这样的问题.
将PropertyChangedEventHandler 写成
public event PropertyChangedCallback PropertyChanged;了..   回复  引用  查看    

#33楼  2008-06-30 21:33 botsing [未注册用户]

@libo
我也遇到了这样的问题,那个方法名必须要定义为PropertyChanged,大小写敏感,我就是把p小写了就出错了   回复  引用  查看    

#34楼  2008-07-01 14:44 游民一族      

呵呵,遇到两个问题:
1. 把“public class User {...”前面的public去了绑定就报异常,很是奇怪,在同一个程序里public修饰符应该不是必需的吧!
2. 不能绑定到Page上,写了个LayoutRoot.DataContext = this,一运行就报错,郁闷   回复  引用  查看    

#35楼 [楼主] 2008-07-01 22:15 TerryLee      

@游民一族
1.必须为public

2.LayoutRoot.DataContext=this,搞明白这里的this是什么,呵呵   回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-03-09 17:18 编辑过
 
另存  打印
最新IT新闻:
· 阿里巴巴确立未来十年战略规划 修改自身定位
· 微软高管:Wii用户最终会成为Xbox 360用户
· 遵守YouTube案裁定 谷歌将陷入隐私指控深渊
· iPhone入华在即 中国手机产业生存面临考验
· 阿里巴巴集团再向淘宝注资20亿元
 


导航

公告

  • 网名:TerryLee
  • 本名:李会军
  • 位置:中国北京 Ethos
  • 联系方式:
  • 个人主页

 MVP配置

 版权声明

  • 本站采用创作共用许可 署名,非商业

绿色通道

IT新闻

统计

与我联系

留言簿(311)

我的标签

随笔分类

随笔档案

个人站点

关注项目

好的网站

我的好友

友情博客