Silverlight DataBindings for 1.1 (Managed code)
文/黃忠成
RC1方興未艾,RC2已在路上了,看來1.0 Release之日不遠了!前面一篇文章利用了PageMethods與JavaScript為Silverlight 1.0RC加上DataBindings的功能,此次舞台換到了Silverlight 1.1 Alpha Refresh及Visual Studio 2008 Beta 2上,與1.1時不同,這次已無法用單一的Web Site模式實作,基於ASP.NET Ajax與Silverlight所使用的CLR Runtime不同,我們必須將Silverlight與ASP.NET Ajax拆開,別誤會!這並非意味你無法將Silverlight與ASP.NET Ajax放在同一個虛擬目錄下,Silverlight 1.1使用的Binary目錄是ClientBin,ASP.NET是Bin,兩者並無衝突,限制只在於你必須將Silverlight與ASP.NET Ajax分成兩個Project來編譯,在Silverlight編譯完成後將.xaml、.js複製到ASP.NET Ajax的專案目錄下,再將.dll複製到ASP.NET Ajax的ClientBin目錄下即可。回到主題,在Silverlight 1.1中,實現Data Bindings除了可以用前一篇文章的JavaScript技巧外,還多了一個選擇,那就是使用C#等Managed的語言,SLDH.js的C#版本如下。
SLDH.cs
/////////////////////////////////////////////////////////////////////////
// Silverlight Data Binding Helper 0.1 for Silverlight 1.1 Alpha Refresh
/////////////////////////////////////////////////////////////////////////
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser.Net;
using System.Windows.Browser.Serialization;
namespace SilverlightDataHelper
{
public class JSONDataRow
{
private Listobject> _columns;
private Listobject> _values;
public object this[int index]
{
get
{
return _values[index];
}
}
public object this[string name]
{
get
{
for (int i = 0; i
{
if (((string)_columns[i]).Equals(name))
return _values[i];
}
return null;
}
}
internal JSONDataRow(object[] columns, object[] values)
{
_columns = new Listobject>(columns);
_values = new Listobject>(values);
}
}
public class BindingData
{
private bool _bindingComplete = false;
private string _bindingProperty = string.Empty;
private string _bindingField = string.Empty;
private FrameworkElement _control;
private string _format = string.Empty;
private PropertyInfo _cachedProp = null;
public bool BindingComplete
{
get
{
return this._bindingComplete;
}
}
public string BindingProperty
{
get
{
return _bindingProperty;
}
}
public string BindingField
{
get
{
return _bindingField;
}
}
public FrameworkElement Control
{
get
{
return _control;
}
}
public string Format
{
get
{
return _format;
}
set
{
_format = value;
}
}
public void UpdateValue(JSONDataRow dataItem)
{
if (_bindingComplete)
{
if (_cachedProp == null)
{
_cachedProp = _control.GetType().GetProperty(_bindingProperty);
if (_cachedProp == null)
_bindingComplete = false;
}
if (_cachedProp != null && Format != string.Empty)
{
if (_cachedProp.PropertyType == typeof(Uri))
{
Uri uri = new Uri(string.Format(Format,
dataItem[BindingField]), UriKind.Relative);
_cachedProp.SetValue(_control, uri, null);
}
else
_cachedProp.SetValue(_control, string.Format(Format,
dataItem[BindingField]), null);
}
else if (_cachedProp != null)
_cachedProp.SetValue(_control, dataItem[BindingField], null);
}
}
public BindingData(FrameworkElement ctrl, string bindingExpression)
{
string[] bindings = bindingExpression.Split(';');
_bindingComplete = false;
_control = ctrl;
for (int i = 0; i
{
string[] temp = bindings[i].Split(':');
if (temp.Length != 2)
{
_bindingComplete = false;
return;
}
if (temp[0].ToLower() == "bindingfield")
_bindingField = temp[1];
else if (temp[0].ToLower() == "bindingproperty")
_bindingProperty = temp[1];
else if (temp[0].ToLower() == "format")
_format = temp[1];
}
if (_bindingField != string.Empty &&
_bindingProperty != string.Empty)
_bindingComplete = true;
}
}
public class BindingContext
{
private Panel _container;
private ListBindingData> _bindingControls = null;
private bool _bindingComplete = false;
private int _position = 0;
private int _count = -1;
private string _serviceUrl = string.Empty;
private string _bindingMethod = string.Empty;
private string _bindingCountMethod = string.Empty;
private string _countMethod = string.Empty;
public int Position
{
get
{
return _position;
}
set
{
if (_position != value && value value >= 0)
{
_position = value;
UpdateBinding();
}
}
}
public int Count
{
get
{
return _count;
}
}
public bool BindingComplete
{
get
{
return _bindingComplete;
}
}
public ListBindingData> BindingControls
{
get
{
if (_bindingControls == null)
_bindingControls = new ListBindingData>();
return _bindingControls;
}
}
private void ChildWorker(FrameworkElement elem)
{
string exprsssion = elem.Tag == null ? string.Empty : elem.Tag;
BindingData data = new BindingData(elem, exprsssion);
if (data.BindingComplete)
BindingControls.Add(data);
if (elem is Panel)
{
Panel pnl = (Panel)elem;
for (int i = 0; i
{
if (pnl.Children[i] is FrameworkElement)
ChildWorker((FrameworkElement)pnl.Children[i]);
}
}
}
private void FetchCount()
{
BrowserHttpWebRequest request =
new BrowserHttpWebRequest(new Uri(_serviceUrl + "/" +
_bindingCountMethod, UriKind.Relative));
request.ContentType = "application/json; charset=utf-8";
request.Method = "POST";
request.ContentLength = 0;
request.Referer = System.Windows.Browser.HtmlPage.DocumentUri.AbsolutePath;
request.Accept = "/*/";
HttpWebResponse response = request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream());
JavaScriptSerializer serializer = new JavaScriptSerializer();
string data = sr.ReadToEnd();
_count = serializer.Deserializeint>(data);
sr.Close();
response.Close();
request.Close();
}
private JSONDataRow FetchData(int index)
{
BrowserHttpWebRequest request =
new BrowserHttpWebRequest(new Uri(_serviceUrl + "/" +
_bindingMethod, UriKind.Relative));
JavaScriptSerializer serializer = new JavaScriptSerializer();
request.ContentType = "application/json; charset=utf-8";
request.Method = "POST";
request.Referer = System.Windows.Browser.HtmlPage.DocumentUri.AbsolutePath;
request.Accept = "/*/";
Stream reqStream = request.GetRequestStream();
byte[] buff = Encoding.UTF8.GetBytes("{index:" + index.ToString() + "}");
reqStream.Write(buff, 0, buff.Length);
request.ContentLength = buff.Length;
HttpWebResponse response = request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream());
string data = sr.ReadToEnd();
sr.Close();
response.Close();
request.Close();
object[] parsedData = serializer.Deserializeobject[]>(data);
return new JSONDataRow((object[])parsedData[0], (object[])parsedData[1]);
}
private void UpdateBinding()
{
JSONDataRow row = FetchData(Position);
foreach (BindingData item in BindingControls)
item.UpdateValue(row);
}
public void Initialize()
{
ChildWorker(_container);
FetchCount();
UpdateBinding();
}
public BindingContext(Panel container)
{
_container = container;
if (_container.Tag == null)
{
_bindingComplete = false;
return;
}
string[] parseBinding = container.Tag.Split(':');
_bindingComplete = false;
if (parseBinding.Length == 2 && parseBinding[0].ToLower() == "bindingcontext")
{
string[] bindingMethods = parseBinding[1].Split(',');
if (bindingMethods.Length == 3)
{
_serviceUrl = bindingMethods[0];
_bindingMethod = bindingMethods[1];
_bindingCountMethod = bindingMethods[2];
_bindingComplete = true;
}
}
if (_bindingComplete)
ChildWorker(container);
}
}
}
|
ㄟ...程式碼變長了哦~~~ >"
Default.aspx.cs
using System;
using System.IO;
using System.Data;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;
using System.Web.Services;
public partial class _Default : System.Web.UI.Page
{
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["
ConnectionString"].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;
}
}
}
private static Listobject> BuildJSONRow(DataRow row)
{
Listobject> result = new Listobject>();
Liststring> columns = new Liststring>();
Listobject> values = new Listobject>();
foreach (DataColumn col in row.Table.Columns)
{
columns.Add(col.ColumnName);
values.Add(row.IsNull(col) ? string.Empty : row[col].ToString());
}
result.Add(columns);
result.Add(values);
return result;
}
[WebMethod]
public static Listobject> GetData(int index)
{
DataTable table = BuildDataCache();
return BuildJSONRow(table.DefaultView[index].Row);
}
[WebMethod]
public static int GetCount()
{
DataTable table = BuildDataCache();
return table.DefaultView.Count;
}
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["ID"] != null &&
Request.QueryString["ID"].Length > 0)
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings[
"ConnectionString"].ConnectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand(
"SELECT Photo FROM Employees WHERE EmployeeID = @ID", conn);
cmd.Parameters.AddWithValue("@ID", Request.QueryString["ID"]);
object data = cmd.ExecuteScalar();
if (data != null && ((byte[])data).Length > 0)
{
Response.Clear();
Response.BufferOutput = true;
Response.ContentType = "image/jpeg";
MemoryStream ms = new MemoryStream();
ms.Write(((byte[])data), 78, ((byte[])data).Length - 78);
MemoryStream jpegms = new MemoryStream();
System.Drawing.Image.FromStream(ms).Save(jpegms,
System.Drawing.Imaging.ImageFormat.Jpeg);
jpegms.Position = 0;
Response.OutputStream.Write(jpegms.GetBuffer(), 0, (int)jpegms.Length);
ms.Dispose();
jpegms.Dispose();
Response.Flush();
Response.End();
}
}
}
}
}
|
當需要做DataBindings時,只需要在.xaml.cs的Page_Loaded事件處理函式中建立此物件即可,見下面程式碼。
Page.xaml
Canvasx:Name="parentCanvas"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="Page_Loaded"
x:Class="SilverlightProject1.Page;assembly=ClientBin/SilverlightProject1.dll"
Width="640"
Height="480"
Background="White"
>
CanvasName="DataDemo"Height="600"Width="800"
Tag="BindingContext:Default.aspx,GetData,GetCount">
Canvas.Background>
LinearGradientBrush>
GradientStopColor="Yellow"Offset="0.0" />
GradientStopColor="Orange"Offset="0.5" />
GradientStopColor="Red"Offset="1.0" />
LinearGradientBrush>
Canvas.Background>
TextBlockTag="BindingField:EmployeeID;BindingProperty:Text"
Name="txtEmployeeID"Width="144"Height="24"Canvas.Left="166"
|