数据源控件是 Microsoft Visual Studio
中引入的一种新型服务器控件
它们是数据绑定体系结构的一个关键部分
能够通过数据绑定控件来提供声明性编程模型和自动数据绑定行为
本文及此系列中的后续几篇文章将介绍实现数据源控件的核心内容
引言
简而言之数据源控件概括了一个数据存储和可以针对所包含的数据执行的一些操作DataBound 控件通过其 DataSourceID 属性与一个数据源控件相关联大多数传统的数据存储要么是表格格式要么是分层的数据源控件也相应地分为两类在此要介绍的是表格格式的数据源控件
数据源控件自身并不能发挥多大作用所有逻辑都封装在 DataSourceView 派生的类中至少有一个 DataSourceView 必须实现检索(即 SELECT)一组行的功能它可以提供修改数据(即 INSERTUPDATE 和 DELETE)的功能(可选)数据绑定控件可通过各种 Can??? 属性来检查启用功能集数据源控件本身只是一个或多个唯一命名视图的容器依据惯例默认视图可以按其名称进行访问也可以为空不同视图之间是否存在关系或者存在怎样的关系可以根据每个数据源控件的实现情况来进行适当的定义例如某个数据源控件可能会通过不同的视图对同一个数据提供不同的经筛选的视图或者可能会在辅助视图中提供一组子行可使用数据绑定控件的 DataMember 属性来选择某个特殊的视图(如果该数据源控件提供了多个视图)请注意Whidbey 中的所有内置数据源控件目前都不提供多个视图
最后再介绍一点内容数据源控件(及其视图)会实现两组 API第一组 API 是就四种常用的数据操作而定义的一个抽象界面以常规方式从任一数据绑定控件中使用第二组是可选的它使用其表示的域或数据存储方面的术语来定义通常被强类型化且面向应用程序开发人员
示例
在这些文章中将实现一个 WeatherDataSource它将针对由 (英文)提供的 REST(英文)XML API 来工作以便根据邮政编码来检索天气信息通常会首先实现派生的数据源控件
public class WeatherDataSource : DataSourceControl {
public static readonly string
CurrentConditionsViewName = CurrentConditions;
private WeatherDataSourceView _currentConditionsView;
private WeatherDataSourceView CurrentConditionsView {
get {
if (_currentConditionsView == null) {
_currentConditionsView = new WeatherDataSourceView(this CurrentConditionsViewName);
}
return _currentConditionsView;
}
}
public string ZipCode {
get {
string s = (string)ViewState[ZipCode];
return (s != null) ? s : StringEmpty;
}
set {
if (StringCompare(value ZipCode
StringComparisonOrdinal) != ) {
ViewState[ZipCode] = value;
CurrentConditionsViewRaiseChangedEvent();
}
}
}
protected override DataSourceView GetView(string viewName) {
if (StringIsNullOrEmpty(viewName) ||
(StringCompare(viewName CurrentConditionsViewName
StringComparisonOrdinalIgnoreCase) == )) {
return CurrentConditionsView;
}
throw new ArgumentOutOfRangeException(viewName);
}
protected override ICollection GetViewNames() {
return new string[] { CurrentConditionsViewName };
}
public Weather GetWeather() {
return CurrentConditionViewGetWeather();
}
}
如您所见基本的理念是实现 GetView 以返回一个命名视图实例以及实现 GetViewNames 以返回可用视图集
在此选择从 DataSourceControl 中派生有一点是不易察觉的事实上数据绑定控件要查找 IDataSource 界面而 DataSource 控件通过实现 GetView 和 GetViewNames 来实现该界面之所以需要界面是为了使数据源控件能够既是表格格式又是分层的(如果可能的话)在这种情况下从主要模型中派生并将另一个模型作为界面来实现)其次还允许在各种方案中转换其他控件以使数据源的容量加倍 另外还要注意公共 ZipCode 属性和返回强类型化 Weather 对象的 GetWeather 方法此 API 适合于页面开发人员页面开发人员无需考虑 DataSourceControl 和 DataSourceView
下一步是实现数据源视图本身此特定示例仅提供了 SELECT 级功能(这只是最低要求也是在此方案中唯一有用的功能)
private sealed class WeatherDataSourceView : DataSourceView {
private WeatherDataSource _owner;
public WeatherDataSourceView(WeatherDataSource owner string viewName)
: base(owner viewName) {
_owner = owner;
}
protected override IEnumerable ExecuteSelect(
DataSourceSelectArguments arguments) {
argumentsRaiseUnsupportedCapabilitiesError(this);
Weather weatherObject = GetWeather();
return new Weather[] { weatherObject };
}
internal Weather GetWeather() {
string zipCode = _ownerZipCode;
if (zipCodeLength == ) {
throw new InvalidOperationException();
}
WeatherService weatherService = new WeatherService(zipCode);
return weatherServiceGetWeather();
}
internal void RaiseChangedEvent() {
OnDataSourceViewChanged(EventArgsEmpty);
}
}
默认情况下DataSourceView 类从诸如 CanUpdate 等的属性返回 false而从 Update 和相关方法抛出 NotSupportedException在此在 WeatherDataSourceView 中唯一需要做的就是替代抽象的 ExecuteSelect 方法返回包含选定天气数据的 IEnumerable在实现过程中使用了帮助程序 WeatherService 类该类仅使用 WebRequest 对象来查询 (英文)方法是使用所选的邮政编码(这没什么特别的)
您可能注意到了ExecuteSelect 被标记为受保护数据绑定控件实际调用的是在回拨中传递的公共(和密封)Select 方法Select 的实现会调用 ExecuteSelect并调用回拨与得到的 IEnumerable 实例这种模式非常古怪这其中有一个原因此系列随后的文章中将会加以说明请稍候
下面是该用法的示例
Zip Code: <ASP:TextBox runat=server id=zipCodeTextBox />
<asp:Button runat=server onclick=OnLookuPButtonClick Text=查找 />
<hr />
<asp:FormView runat=server DataSourceID=weatherDS>
<ItemTemplate>
<asp:Label runat=server
Text=<%# Eval(Temperature 当前温度是 {}) %> />
</ItemTemplate>
</asp:FormView>
<nk:WeatherDataSource runat=server id=weatherDS ZipCode= />
<script runat=server>
private void OnLookupButtonClick(object sender EventArgs e) {
weatherDSZipCode = zipCodeTextBoxTextTrim();
}
</script>
此代码设置了邮政编码来响应用户输入这会使数据源发出更改通知从而使绑定的 FormView 控件执行数据绑定并更改显示
现在数据访问代码就被封装在数据源控件中此外通过此模型(英文)能够发布一个组件该组件还可以封装特定于其服务的详细信息但愿它会好用此外抽象的数据源界面允许 FormView 仅针对天气数据进行工作
在下一篇文章中将增强数据源控件的功能使其能够自动处理用来查询数据的筛选值(即邮政编码)的更改