Silverlight数据绑定全解析
立即解锁
发布时间: 2025-08-26 01:42:32 阅读量: 12 订阅数: 46 AIGC 

### Silverlight 数据绑定全解析
#### 1. UpdateSourceTrigger 值
在 Silverlight 中,数据绑定的 `UpdateSourceTrigger` 仅支持两个值:`Default` 和 `Explicit`,不像 WPF 那样可以选择 `PropertyChanged`。不过,借助一些代码和 `UpdateSource()` 方法,你能在需要时确保更新操作的执行。当允许用户编辑绑定数据时,就得考虑如何捕捉错误并处理无效数据,Silverlight 提供了多种验证选项来预防数据录入问题。
#### 2. 变更通知
有时候,你可能会在数据对象绑定到一个或多个元素后对其进行修改。例如,下面的代码将当前价格提高了 10%:
```csharp
Product product = (Product)gridProductDetails.DataContext;
product.UnitCost *= 1.1;
```
但这段代码无法达到预期效果。尽管内存中的 `Product` 对象已被修改,但绑定控件中却没有显示出变化。这是因为缺少关键的基础设施,即 `Product` 对象无法通知绑定元素。
为解决此问题,数据类需要实现 `System.ComponentModel.INotifyPropertyChanged` 接口。该接口定义了一个名为 `PropertyChanged` 的事件。当数据对象的属性发生变化时,必须触发 `PropertyChanged` 事件并以字符串形式提供属性名称。
下面是使用 `INotifyPropertyChanged` 接口的改进版 `Product` 类的定义,以及 `PropertyChanged` 事件的实现代码:
```csharp
public class Product : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
...
}
```
现在,需要在所有属性的 `setter` 中触发 `PropertyChanged` 事件:
```csharp
private double unitCost;
public double UnitCost
{
get { return unitCost; }
set {
unitCost = value;
OnPropertyChanged(new PropertyChangedEventArgs("UnitCost"));
}
}
```
如果在前面的示例中使用这个版本的 `Product` 类,就能得到预期的行为。当更改当前的 `Product` 对象时,新信息会立即显示在绑定的文本框中。
**提示**:如果多个值发生了变化,可以调用 `OnPropertyChanged()` 并传入一个空字符串,这会通知 Silverlight 重新评估绑定到类中任何属性的绑定表达式。
#### 3. 调试数据绑定表达式
数据绑定错误很容易出现,但却难以捕捉。例如,若绑定到一个不存在的属性,编译时不会有有用的错误信息指出问题,只会看到原本应显示数据的文本框为空。如果属性是私有的,或者属性的 `getter` 抛出异常,也会出现同样的情况。同样,如果属性的 `setter` 抛出异常,或者 Silverlight 无法将编辑后的值转换为适当的数据类型,编辑操作就会失败。
如果数据绑定错误是由用户编辑导致的,可能无法预防该问题,但可以使用验证来识别错误并通知用户。如果问题是由代码错误引起的,就需要在应用程序继续运行之前找出并修复它。
幸运的是,Silverlight 有一个方便的调试功能,可用于剖析数据绑定问题。使用该功能时,首先要在有问题的绑定表达式上设置断点。具体操作是在 Visual Studio 中打开 XAML 文件,然后点击绑定表达式旁边的边距。
此时,Visual Studio 会在执行绑定表达式后、显示结果前立即进入中断模式。这时可以调查绑定信息,或者按 F5 继续运行应用程序。如果要检查多个绑定表达式,可以同时设置多个断点。
调查绑定的最佳工具是“局部变量”窗口。当遇到数据绑定断点时,“局部变量”窗口会显示 `BindingState` 对象。展开该对象,会看到一些有用的属性。例如,`Action` 属性能确切告诉你绑定表达式被调用的原因。如果设置为 `UpdatingTarget`,表示绑定表达式即将将值放入绑定控件;如果设置为 `UpdatingSource`,表示绑定表达式即将将用户编辑的值应用到数据源。同样,可以检查 `LastCompletedStage` 属性,以确定断点触发前发生了什么。例如,如果 `LastCompletedStage` 设置为 `TypeConversion`,而绑定表达式显示错误,就可以合理推测是数据转换出了问题。
到目前为止,`BindingState` 最有用的属性是 `Error` 属性。如果存在问题,它会提供一个详细描述当前问题的异常对象。
**注意**:只有当存在实际的绑定数据对象时,才会计算数据绑定表达式。如果数据对象为 `null`,Silverlight 不会采取任何行动,断点也不会触发。不过,可以使用 `FallbackValue` 属性来替代不同的值。
#### 4. 构建数据服务
前面看到的示例虽然介绍了 Silverlight 数据绑定的基本细节,但不够真实。更典型的设计是让 Silverlight 应用程序从外部源(如 Web 服务)检索所需的数据对象。在构建数据服务时,首先要将数据对象的类定义移到 ASP.NET 网站。如果创建的是无项目网站,必须将代码文件放在 `App_Code` 文件夹中;如果创建的是 Web 项目,则可以放在任何位置。数据对象需要进行一些修改,添加 `DataContract` 和 `DataMember` 属性使其可序列化,并添加一个公共无参构造函数以允许序列化。
以下是部分代码示例,展示了所需的大致框架:
```csharp
[DataContract()]
public class Product : INotifyPropertyChanged
{
private string modelNumber;
[DataMember()]
public string ModelNumber
{
get { return modelNumber; }
set
{
modelNumber = value;
OnPropertyChanged(new PropertyChangedEventArgs("ModelNumber"));
}
}
private string modelName;
[DataMember()]
public string ModelName
{
get { return modelName; }
set
{
modelName = value;
OnPropertyChanged(new PropertyChangedEventArgs("ModelName"));
}
}
...
public Product(){}
}
```
当使用 Web 服务定义数据类时,Silverlight 会自动提供更改通知。因为当 Visual Studio 生成数据类的客户端副本时,即使服务器端的原始类没有实现 `INotifyPropertyChanged` 接口,客户端副本也会自动实现该接口。
以下是一个超简单的 `Product` 类定义:
```csharp
[DataContract()]
public class Product : INotifyPropertyChanged
{
[DataMember()]
public string ModelNumber { get; set; }
[DataMember()]
public string ModelName { get; set; }
[DataMember()]
public decimal UnitCost { get; set; }
[DataMember()]
public string Description{ get; set; }
}
```
客户端副本仍然会实现 `INotifyPropertyChanged` 接口,具有完整的属性过程,并在任何属性发生变化时调用 `OnPropertyChanged()` 来触发通知事件。
可以通过打开 Silverlight 项目中的 `Reference.cs` 文件来检查数据类的客户端代码。需要注意的是,这个文件是隐藏的,要先在“解决方案资源管理器”中点击“显示所有文件”按钮才能看到它。
这里有一个问题值得思考:如果客户端会自动实现 `INotifyPropertyChanged` 接口,是否还有必要在服务器端实现它呢?这取决于个人偏好。有些开发者认为在服务器端显式实现该接口更清晰,而另一些开发者则觉得更改通知主要是客户端功能,在服务器端很少使用,所以不必实现。
最后,还可以禁用此功能,告诉 Visual Studio 在生成客户端数据类时不使用 `INotifyPropertyChanged` 接口。具体做法是编辑 Silverlight 属性中的 `Reference.svcmap` 文件,找到 `<EnableDataBinding>` 元素,将其内容从 `true` 改为 `false`。不过,通常没有必要这样做。
有了数据对象后,还需要一个使用它的 Web 服务方法。以下是 Web 服务类的基本框架:
```csharp
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class StoreDb
{
private string connectionString =
WebConfigurationManager.ConnectionStrings["StoreDb"].ConnectionString;
[OperationContract()]
public Product GetProduct(int ID)
{
...
}
}
```
查询是通过数据库中名为 `GetProduct` 的存储过程执行的。连接字符串不是硬编码的,而是通过 `web.config` 文件中的设置获取,这样便于后续修改。以下是 `web.config` 文件中定义连接字符串的部分:
```xml
<configuration>
...
<connectionStrings>
<add name="StoreDb" connectionString=
"Data Source=localhost;Initial Catalog=Store;Integr
```
0
0
复制全文
相关推荐










