private static DataTable BuildDataCache()
{
if (HttpRuntime.Cache["DataCache_Employees"] != null)
return HttpRuntime.Cache["DataCache_Employees"] as DataTable;
else
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings[
"NorthwindConnectionString"].ConnectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT * FROM Employees ORDER BY EmployeeID", conn);
DataTable table = new DataTable("Employees");
adapter.Fill(table);
HttpRuntime.Cache["DataCache_Employees"] = table;
return table;
}
}
}
[WebMethod]
public static Employee GetData(int index)
{
DataTable table = BuildDataCache();
return new Employee(table.DefaultView[index]);
}
[WebMethod]
public static int GetCount()
{
DataTable table = BuildDataCache();
return table.DefaultView.Count;
}
protected void Button1_Click(object sender, EventArgs e)
{
}
}
[Serializable]
public class Employee
{
[NonSerialized]
private DataRowView _rv = null;
public string EmployeeID
{
get
{
return (_rv.Row.IsNull("EmployeeID") ? string.Empty : _rv["EmployeeID"].ToString());
}
}
public string LastName
{
get
{
return (_rv.Row.IsNull("LastName") ? string.Empty : (string)_rv["LastName"]);
}
}
public string FirstName
{
get
{
return (_rv.Row.IsNull("FirstName") ? string.Empty : (string)_rv["FirstName"]);
}
}
public string Title
{
get
{
return (_rv.Row.IsNull("Title") ? string.Empty : (string)_rv["Title"]);
}
}
public string HireDate
{
get
{
return (_rv.Row.IsNull("HireDate") ?
string.Empty : ((DateTime)_rv["HireDate"]).ToShortDateString());
}
}
public Employee(DataRowView rv)
{
_rv = rv;
}
}
运用 ASP.NET Ajax 及 JSON,我们可以轻易的用 JavaScript 来取得资料库的资料,接着只要将资料设定给指定 Silverlight 控制项即可,这个工作可以简单化也可以复杂化,简单的作法是直接在 JavaScript 以 findName 来取得控制项,然后一一设定其属性值。
handleLoad: function(plugIn, userContext, rootElement)
{
this.plugIn = plugIn;
this.dataContext = rootElement.children.getItem(0);
PageMethods.GetCount(this.OnSucceeded,this.OnFailed,this);
this.receiveData(this.currentDataIndex);
},
OnSucceeded: function(result, userContext, methodName)
{
if (methodName == "GetData")
{
userContext.displayData(result);
}
else if(methodName == "GetCount")
userContext.recordCount = result;
},
OnFailed:function(error, userContext, methodName)
{
if(error !== null)
{
alert(error.get_message());
}
},
displayData: function(data)
{
var idCtrl = this.dataContext.findName('txtEmployeeID');
var firstNameCtrl = this.dataContext.findName('txtLastName');
var lastNameCtrl = this.dataContext.findName('txtFirstName');
var titleCtrl = this.dataContext.findName('txtTitle');
var hireDateCtrl = this.dataContext.findName('txtHireDate');
var imgCtrl = this.dataContext.findName("imgPhoto");
idCtrl.text = data.EmployeeID;
firstNameCtrl.text = data.FirstName;
lastNameCtrl.text = data.LastName;
titleCtrl.text = data.Title;
hireDateCtrl.text = data.HireDate;
imgCtrl.source = "Default.aspx?ID="+idCtrl.text;
this.dataContext.findName("imgAnimation").begin();
}
这种做法的缺点是设计师得用 JavaScript 写下许多程式码。另一种做法是利用 Silverlight 控制项的 Tag 属性,指定 Binding Expression,然后于 JavaScript 中巡览她们来一一指定值,如下列片段所示。
<Canvas XMLns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas Name="DataDemo" Height="600" Width="800" Tag="BindingContext:GetData,GetCount">
<Canvas.Background>
<LinearGradientBrush>
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Orange" Offset="0.5" />
<GradientStop Color="Red" Offset="1.0" />
</LinearGradientBrush>
</Canvas.Background>
<TextBlock Tag="BindingField:EmployeeID;BindingProperty:Text" Name="txtEmployeeID" Width="144" Height="24" Canvas.Left="166" Canvas.Top="23" Tt="A00001" TextWrapping="Wrap"/>
<TextBlock Tag="BindingField:LastName;BindingProperty:Text" Name="txtLastName" Width="320" Height="24" Canvas.Left="500" Canvas.Top="23" Text="Alean Company" TextWrapping="Wrap"/>
<TextBlock Tag="BindingField:FirstName;BindingProperty:Text" Name="txtFirstName" Width="320" Height="24" Canvas.Left="166" Canvas.Top="72" Text="Jeffray" TextWrapping="Wrap"/>
<TextBlock Tag="BindingField:Title;BindingProperty:Text" Name="txtTitle" Width="576" Height="24" Canvas.Left="166" Canvas.Top="122" Text="Taipen 101" TextWrapping="Wrap"/>
<TextBlock Tag="BindingField:HireDate;BindingProperty:Text" Name="txtHireDate" Width="576" Height="24" Canvas.Left="166" Canvas.Top="171" Text="2005/3/4" TextWrapping="Wrap"/>
<Image Name="imgPhoto" Tag="BindingField:EmployeeID;BindingProperty:Source;Format:Default.aspx?ID={0}" Width="357" Height="206" Canvas.Left="400" Canvas.Top="301">
<Image.Triggers>
<EventTrigger RoutedEvent="Image.Loaded">
<BeginStoryboard>
<Storyboard Name="imgAnimation">
<DoubleAnimation
Storyboard.TargetName="imgPhoto"
Storyboard.TargetProperty="Opacity"
From="0.0" To="1.0" Duration="0:0:6"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
<TextBlock Name="txtLabel1" Width="114" Height="24" Canvas.Left="18" Canvas.Top="23" Text="Employee ID:" TextWrapping="Wrap"/>
<TextBlock Name="txtLabel1_Copy" Width="120" Height="24" Canvas.Left="349" Canvas.Top="23" Text="Last Name:" TextWrapping="Wrap"/>
<TextBlock Name="txtLabel1_Copy1" Width="130" Height="24" Canvas.Left="18" Canvas.Top="72" Text="First Name:" TextWrapping="Wrap"/>
<TextBlock Name="txtLabel1_Copy2" Width="104" Height="24" Canvas.Left="18" Canvas.Top="122" Text="Title :" TextWrapping="Wrap"/>
<TextBlock Name="txtLabel1_Copy3" Width="93" Height="24" Canvas.Left="18" Canvas.Top="171" Text="Hire Date:" TextWrapping="Wrap"/>
</Canvas>
</Canvas>
那如何解析 Tag 的 Binding Expression 并指定值呢?答案是利用 Silverlight 的 JavaScript 支援,一一巡览所有控制项,一一解析 Tag,然后再指定值。
/////////////////////////////////////////////////////////////////////////
// Silverlight Data Binding Helper 0.1
/////////////////////////////////////////////////////////////////////////
if (!window.SilverlightBinding)
window.SilverlightBinding = {};
SilverlightBinding.BindingData = function(ctrl,bindingExpression)
{
var bindings = bindingExpression.split(';');
this.bindingComplete = false;
this.ctrl = ctrl;
for(var i = 0; i < bindings.length; i++)
{
var temp = bindings[i].split(':');
if(temp.length != 2)
{
this.bindingComplete = false;
return;
}
if(temp[0] == 'BindingField')
this.bindingField = temp[1];
else if(temp[0] == 'BindingProperty')
this.bindingProperty = temp[1];
else if(temp[0] == 'Format')
this.format = temp[1];
}
this.bindingComplete = true;
}
SilverlightBinding.BindingData.prototype =
{
updateValue : function(dataItem)
{
if(this.bindingComplete)
{
if(this.format)
eval('this.ctrl.'+this.bindingProperty+
" = this.format.replace('{0}',dataItem."+this.bindingField+');');
else
eval('this.ctrl.'+this.bindingProperty+' = dataItem.'+this.bindingField+';');
}
}
}
SilverlightBinding.BindingContext = function(bindingContainer)
{
var parseBinding = bindingContainer.tag.split(':');
this.bindingComplete = false;
this.bindingContainer = bindingContainer;
this.bindingControls = new Array();
this.currentDataIndex = 0;
this.recordCount = 0;
if(parseBinding.length == 2 && parseBinding[0] == "BindingContext")
{
var bindingMethods = parseBinding[1].split(',');
if(bindingMethods.length == 2)
{
this.bindingMethod = bindingMethods[0];
this.bindingCountMethod = bindingMethods[1];
this.bindingComplete = true;
}
}
if(!this.bindingComplete) alert('ERROR,Binding Failed.');
}
SilverlightBinding.BindingContext.prototype =
{
_childWorker : function(parent,parseParent)
{
if(parent.tag && parent.tag != '')
{
if(parseParent)
{
var bindingData = new SilverlightBinding.BindingData(parent,parent.tag);
if(bindingData.bindingComplete)
{
this.bindingControls.length++;
this.bindingControls[this.bindingControls.length-1] = bindingData;
}
else
delete bindingData;
}
try
{
var temp = parent.children;
}
catch(err)
{
return;
}
for(var i = 0; i < parent.children.count; i++)
this._childWorker(parent.children.getItem(i),true);
}
},
initialize:function()
{
this._childWorker(this.bindingContainer,false);
this._receiveCount();
this._receiveData(0);
},
OnSucceeded: function(result, userContext, methodName)
{
if (methodName == userContext.bindingMethod)
{
for(var i = 0; i < userContext.bindingControls.length; i++)
userContext.bindingControls[i].updateValue(result);
}
else if(methodName == userContext.bindingCountMethod)
userContext.recordCount = result;
},
OnFailed:function(error, userContext, methodName)
{
if(error !== null)
{
alert(error.get_message());
}
},
_receiveData: function(index)
{
eval('PageMethods.'+this.bindingMethod+
'(index,this.OnSucceeded,this.OnFailed,this);');
},
_receiveCount: function()
{
eval('PageMethods.'+this.bindingCountMethod+
'(this.OnSucceeded,this.OnFailed,this);');
},
next:function()
{
if(this.currentDataIndex+1 >= this.recordCount)
return;
this._receiveData(++this.currentDataIndex);
},
prev:function()
{
if(this.currentDataIndex -1 < 0)
return;
this._receiveData(--this.currentDataIndex);
}
}
使用此 JavaScript 物件的方法很简单,只要于 handleLoad 中建立此物件,然后将 Silverlight 的根控制项传入即可。
handleLoad: function(plugIn, userContext, rootElement)
{
this.plugIn = plugIn;
this.dataContext = rootElement.children.getItem(0);
this.bindingContext =
new SilverlightBinding.BindingContext(rootElement.children.getItem(0));
this.bindingContext.initialize();
}
切换上下笔时也很简单。
function Next()
{
window.Silverlight.current_DataContext.bindingContext.next();
window.Silverlight.current_DataContext.dataContext.findName("imgAnimation").begin();
}
function Prev()
{
window.Silverlight.current_DataContext.bindingContext.prev();
window.Silverlight.current_DataContext.dataContext.findName("imgAnimation").begin();
}
下图为执行画面。

本例下载位址:
http://www.dreams.idv.tw/~code6421/files/SLDataDemo1.zip
原文:http://www.microsoft.com/taiwan/msdn/columns/huang_jhong_cheng/Silverlight_Data_Bindings.htm