by Emil
20. July 2009 10:52
您是否知道,当 UpdatePanel 控件对服务器执行异步 AJAX 回调以更新其内容时,这个请求包含了常规 ASP.NET 回发所包含的一切,其中还包括视图状态呢?在许多情况下,从性能的角度而言,应用程序最好是不使用 UpdatePanel,而是使用对 WebMethods 或页面方法的异步调用。这样做可能会大幅度降低网络传输中的数据量。其实,只要您了解为 UpdatePanel 提供客户端支持的 Microsoft® AJAX Library 中的 PageRequestManager、JavaScript 类,这里面许多问题就可以迎刃而解。
更新突出显示
PageRequestManager 可以在更新前和更新后激发浏览器中的事件。您可以将 JavaScript 中的这些事件关联起来,并运行可以提醒用户注意更新内容的代码。关键事件被命名为 pageLoaded。此事件每次都会激发浏览器中的页面加载(它类似 Page_Load in ASP.NET)。您可以使用两行代码(可以合并为一行)注册 pageLoaded 事件的 JavaScript 处理程序:
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(pageLoaded);
第一行获得对该页面的 PageRequestManager 对象的引用。第二行注册名为 pageLoaded 的 JavaScript 函数,作为 pageLoaded 事件的处理程序。
调用时,pageLoaded 事件处理程序会收到一个 Sys.WebForms.PageLoadedEventArgs 类型的参数,它是 Microsoft AJAX Library 中的另一个类。PageLoadedEventArgs 包含一个 get_panelsUpdated 方法,您可以调用该方法来枚举所有的 UpdatePanel(如果有),其内容刚刚已更新。在默认情况下,UpdatePanel 就是客户端上的 DIV,因此您可以使用 JavaScript 来使该 DIV 闪光,突出显示它,或对它执行任何您想要的操作,以提醒用户注意它。
图 1 列出的代码显示了一个使用 pageLoaded 事件来执行更新突出显示的方法。每次更新时,这个 JavaScript 都会使表示已更新的 UpdatePanel 的文档对象模型 (DOM) 元素闪光,方法是使它们依次快速显示和隐藏三次。闪光是通过名为 flashPanels 的帮助器函数来执行的,它将闪光次数作为输入参数。
Figure 1 闪光更新
<script type=”text/javascript”>
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(pageLoaded);
var _panels, _count;
function pageLoaded(sender, args)
{
if (_panels != undefined && _panels.length > 0)
{
for (i=0; i < _panels.length; i++)
_panels[i].dispose();
}
var panels = args.get_panelsUpdated();
if (panels.length > 0)
{
_panels = new Array(panels.length);
for (i=0; i < panels.length; i++)
_panels[i] = new Sys.UI.Control(panels[i]);
flashPanels(3);
}
}
function flashPanels(count)
{
_count = (count << 1) + 1;
for (i=0; i < _panels.length; i++)
_panels[i].set_visible(false);
window.setTimeout(toggleVisibility, 50);
}
function toggleVisibility()
{
for (i=0; i < _panels.length; i++)
_panels[i].set_visible(!_panels[i].get_visible());
if (_count > 0)
window.setTimeout(toggleVisibility, 50);
}
</script>
取消 UpdatePanel 更新
PageRequestManager 激发的另一个重要事件是 initializeRequest,它在发生异步回调之前激发。
是否有可能在运行时决定是否允许 AsyncPostBackTrigger 触发一个 UpdatePanel 更新。回答是肯定的。这个操作通过处理 initializeRequest 事件来完成。
传递到 initializeRequest 处理程序的第二个参数是 initializeRequestEventArgs 类型的一个对象。这个对象包含 get_postBackElement 方法,它可以识别触发更新的按钮或其他元素。它还有一个您可用来在回调发生之前将其取消的 set_cancel 方法。下面是使用中的 set_cancel 方法的示例:
<script type=”text/javascript”>
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(initializeRequest);
function initializeRequest(sender, args)
{
args.set_cancel(!confirm(‘Are you sure?’));
}
</script>
在这个示例中,intializeRequest 处理程序可以在回调执行之前弹出一个确认框,询问用户是否要继续更新。单击确认框中的“Cancel”(取消)可以将 true 传递给 set_cancel,这样可以停止执行回调。在现实生活中,您可能觉得没必要在允许继续更新之前提示用户确认,但如果要是能够根据应用程序中其他地方的条件取消更新,它就可能很有用。
顺便说一下,它还有可能在异步回调执行后但又尚未完成前取消它们。PageRequestManager 提供了 abortPostBack 方法来执行此操作;它还提供了 get_isInAsyncPostBack 方法来确定异步回调是否挂起。这些方法通常与 UpdateProgress 控件一起使用,以便显示取消 UI。
多个 UpdatePanel
一个页面可以承载几个 UpdatePanel。默认情况下,当一个页面上的 UpdatePanel 更新时,该页面的其他 UpdatePanel 也会更新。有时候这是您想要的,但多半您并不需要每个 UpdatePanel 更新来响应其他 UpdatePanel。
通过将页面上每个 UpdatePanel 控件的 UpdateMode 属性设置为 Conditional,您可以选择更新哪个 UpdatePanel 实例(及更新的时间)。然后,在 UpdatePanel 更新和调用服务端事件处理程序的时候,请调用您要更新的其他面板上的 UpdatePanel.Update。这样可以通过减少呈现的控件的数量来减轻服务器的负载,而且它还减少了响应中的数据量,因为不进行更新的 UpdatePanel 不会将任何数据添加到响应中。
68238dc9-b8ff-43eb-a3a1-df5479a09290|0|.0
Tags:
Email2Blog
by Emil
8. July 2009 15:42
委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。
委托方法的使用可以像其他任何方法一样,具有参数和返回值。委托就是给一个函数取了个别的名字。
using System;
// Declare delegate -- defines required signature:
delegate void SampleDelegate(string message);
class MainClass
{
// Regular method that matches signature:
static void SampleDelegateMethod(string message)
{
Console.WriteLine(message);
}
static void Main()
{
// Instantiate delegate with named method:
SampleDelegate d1 = SampleDelegateMethod;
// Instantiate delegate with anonymous method:
SampleDelegate d2 = delegate(string message)
{
Console.WriteLine(message);
};
d1("Hello");
d2("World,http://www.dc9.cn/");
}
}
下面也是委托:
public Form1()
{
InitializeComponent();
this.Click += this.MultiHandler;
}
private void MultiHandler(object sender, System.EventArgs e)
{
MessageBox.Show(((MouseEventArgs)e).Location.ToString());
}
用lambda写就是:
public Form1()
{
InitializeComponent();
this.Click += (sender, e) => {MessageBox.Show(((MouseEventArgs)e).Location.ToString());};
}
--------------------------------------------------------------------------------------------------------------------------------------------
delegate string Printer(string s);
private void button1_Click(object sender, EventArgs e)
{
Printer p =delegate(string j)
{
return j;
};
Console.WriteLine(p("The delegate using the anonymous method is called."));
}
用lambda写就是:
delegate string Printer(string s);
private void button1_Click(object sender, EventArgs e)
{
Printer p = j => j;
Console.WriteLine(p("The delegate using the anonymous method is called."));
}
--------------------------------------------------------------------------------------------------------------------------------------------
或者有名的匿名委托:
delegate void Printer(string s);
private void button1_Click(object sender, EventArgs e)
{
Printer p = new Printer(Form1.DoWork);
p("http://www.dc9.cn/");
}
static void DoWork(string k)
{
System.Console.WriteLine(k);
}
--------------------------------------------------------------------------------------------------------------------------------------------
Where是Enumerable的一个方法。里面的参数是Func<(Of <(T, TResult>)>) 泛型委托
using System;
delegate string ConvertMethod(string inString);
public class DelegateExample
{
public static void Main()
{
// Instantiate delegate to reference UppercaseString method
ConvertMethod convertMeth = UppercaseString;
string name = "Dakota";
// Use delegate instance to call UppercaseString method
Console.WriteLine(convertMeth(name));
}
private static string UppercaseString(string inputString)
{
return inputString.ToUpper();
}
}
写成泛型委托是:
using System;
public class GenericFunc
{
public static void Main()
{
// Instantiate delegate to reference UppercaseString method
Func<string, string> convertMethod = UppercaseString;
string name = "Dakota";
// Use delegate instance to call UppercaseString method
Console.WriteLine(convertMethod(name));
}
private static string UppercaseString(string inputString)
{
return inputString.ToUpper();
}
}
-------------------------------------------------------------------------------------------------------------------------------------------
于是应用到Linq,再变换到lambda:
delegate bool TestFunc(string fruit);
private void button1_Click(object sender, EventArgs e)
{
List<string> fruits =new List<string> {"apple", "http://www.dc9.cn", "banana",
"mango", "orange", "blueberry", "grape", "strawberry" };
TestFunc f = new TestFunc(DoWork);
Func<string, bool> f2 = DoWork;
IEnumerable<string> query = fruits.Where(f2);
foreach (string fruit in query)
Console.WriteLine(fruit);
}
private static bool DoWork(string k)
{
return k.Length < 6;
}
换成lambda写就是:
delegate bool TestFunc(string fruit);
private void button1_Click(object sender, EventArgs e)
{
List<string> fruits =new List<string> { "apple", "passionfruit", "banana", "mango",
"orange", "blueberry", "grape", "http://www.dc9.cn" };
TestFunc f = DoWork;
Func<string, bool> f2 =k=> k.Length < 6;
IEnumerable<string> query = fruits.Where(f2);
foreach (string fruit in query)
Console.WriteLine(fruit);
}
private static bool DoWork(string k)
{
return k.Length < 6;
}
-------------------------------------------------------------------------------------------------------------------------------------------
也能用
private void button1_Click(object sender, EventArgs e)
{
List<string> fruits =new List<string> { "apple", "passionfruit", "banana", "mango",
"orange", "blueberry", "grape", "http://www.dc9.cn" };
IEnumerable<string> query = fruits.Where(
delegate(string k){
return k.Length < 6;
}
);
foreach (string fruit in query)
Console.WriteLine(fruit);
}
换成lambda写就是:
private void button1_Click(object sender, EventArgs e)
{
List<string> fruits =new List<string> { "apple", "passionfruit", "banana","mango",
"orange", "blueberry", "grape", "http://www.dc9.cn" };
IEnumerable<string> query = fruits.Where(k=>k.Length<6);
foreach (string fruit in query)
Console.WriteLine(fruit);
}
--------------------------------------------------------------------------------------------------------------------------------------------
最后再写一个:
public delegate int mydg(int a, int b);
public static class LambdaTest
{
public static int oper(this int a, int b, mydg dg)
{
return dg(a, b);
}
}
Console.WriteLine(oper(2,3, (a, b) => a + b));
Console.WriteLine(oper(2,3, (a, b) => a - b));
ebfd9087-1e01-47bb-9e52-7a04974c14cd|0|.0
Tags:
Email2Blog
by Emil
6. July 2009 15:01
Lambda表达式和匿名方法其实是一件事情。唯一不同的是:他们语法表现形式不同。
Lambda表达式是在语法方面做了更进一步的进化。在本质上,他们是一件事情,作用
都是:产生方法。即:内联方法。所以:我们要了解Lambda 表达式,就应该同时也了解匿名方法。
下面先看一个简单的代码例子,分别用匿名方法和Lambda表达式来实现对数组的搜索:
(1). 使用.net 2.0 的匿名方法来搜索字符串数组中包含 a 的数组元素
static void Main(string[] args)
{
string[] list = new string[] { "abc", "12", "java" };
string[] ll = Array.FindAll(list,
delegate(string s)
{
return s.IndexOf("a") >= 0;
}
);
foreach (string var in ll)
{
Console.WriteLine(var);
}
Console.ReadLine();
}
(2). 使用 .net 3.X 的Lambda表达式来搜索字符串数组中包含 a 的数组元素
static void Main(string[] args)
{
string[] list = new string[] { "abc", "12", "java" };
string[] ll = Array.FindAll(list, s => (s.IndexOf("a") >= 0));
foreach (string var in ll)
{
Console.WriteLine(var);
}
Console.ReadLine();
}
从上述两个例子我们可以看出:从代码书写角度,代码可读性角度来说:
Lambda表达式比匿名方法更简单了。
而 Lambda表达式和匿名方法都是做的同一件事情,让我们少写一个函数定义。
函数的调用和函数的实现在一起完成了。
Lambda表达式的书写格式如下:
(参数列表) => 表达式或者语句块
其中:
参数个数:可以有多个参数,一个参数,或者无参数。
参数类型:可以隐式或者显式定义。
表达式或者语句块:这部分就是我们平常写函数的实现部分(函数体)。
42ba5cfa-b073-4d16-a26a-f71479f1a2b5|0|.0
Tags:
Email2Blog
by Emil
3. July 2009 14:07
利用 ASP.NET ListView 控件,可以绑定从数据源返回的数据项并显示它们。这些数据可以显示在多个页面。您可以逐个显示数据项,也可以对它们分组。
ListView 控件会按照您使用模板和样式定义的格式显示数据。与 DataList 和 Repeater 控件相似,此控件也适用于任何具有重复结构的数据。但与这些控件不同的是,ListView 控件允许用户编辑、插入和删除数据,以及对数据进行排序和分页,所有这一切都无需编写代码。
为 ListView 控件创建模板
与 DataList 和 Repeater 控件类似,ListView 控件显示的项也是用模板定义的。利用 ListView 控件,可以逐项显示数据,也可以按组显示数据。
通过创建 LayoutTemplate 模板,可以定义 ListView 控件的主要(根)布局。LayoutTemplate 必须包含一个充当数据占位符的控件。例如,该布局模板可以包含 ASP.NET Table、Panel 或 Label 控件(它还可以包含 runat 属性设置为“server”的 table、div 或 span 元素)。这些控件将包含 ItemTemplate 模板所定义的每个项的输出,您可以在 GroupTemplate 模板定义的内容中对这些输出进行分组。
在 ItemTemplate 模板中,需要定义各个项的内容。此模板包含的控件通常已绑定到数据列或其他单个数据元素。
可用的模板
下表列出了可用于 ListView 控件的所有模板。
LayoutTemplate
标识定义控件的主要布局的根模板。它包含一个占位符对象,例如表行 (tr)、div 或 span 元素。此元素将由 ItemTemplate 模板或 GroupTemplate 模板中定义的内容替换。它还可能包含一个 DataPager 对象。
ItemTemplate
标识要为各个项显示的数据绑定内容。
ItemSeparatorTemplate
标识要在各个项之间呈现的内容。
GroupTemplate
标识组布局的内容。它包含一个占位符对象,例如表单元格 (td)、div 或 span。该对象将由其他模板(例如 ItemTemplate 和 EmptyItemTemplate 模板)中定义的内容替换。
GroupSeparatorTemplate
标识要在项组之间呈现的内容。
EmptyItemTemplate
标识在使用 GroupTemplate 模板时为空项呈现的内容。例如,如果将 GroupItemCount 属性设置为 5,而从数据源返回的总项数为 8,则 ListView 控件显示的最后一行数据将包含 ItemTemplate 模板指定的3 个项以及 EmptyItemTemplate 模板指定的 2个项。
EmptyDataTemplate
标识在数据源未返回数据时要呈现的内容。
SelectedItemTemplate
标识为区分所选数据项与显示的其他项,而为该所选项呈现的内容。
AlternatingItemTemplate
标识为便于区分连续项,而为交替项呈现的内容。
EditItemTemplate
标识要在编辑项时呈现的内容。对于正在编辑的数据项,将呈现 EditItemTemplate 模板以替代 ItemTemplate 模板。
InsertItemTemplate
标识要在插入项时呈现的内容。将在 ListView 控件显示的项的开始或末尾处呈现 InsertItemTemplate 模板,以替代 ItemTemplate 模板。通过使用 ListView 控件的 InsertItemPosition 属性,可以指定 InsertItemTemplate 模板的呈现位置。
对数据进行分页
若要使用户能够按页查看 ListView 控件中的数据,可以使用 DataPager 控件。DataPager 控件可以位于 LayoutTemplate 模板内部,也可以位于 ListView 控件之外的页面上。如果 DataPager 控件不在 ListView 控件内,则必须将 PagedControlID 属性设置为 ListView 控件的 ID。
DataPager控件支持内置的分页用户界面。您可以使用 NumericPagerField 对象,此对象允许用户按页码选择数据页。此外也可以使用NextPreviousPagerField 对象。利用此对象,用户可以逐页浏览数据页,也可以直接跳到第一个或最后一个数据页。数据页的大小由 DataPager 控件的 Page Size 属性设置。单个 DataPager 控件中可以使用一个或多个页导航字段对象。
另外,通过使用 TemplatePagerField 对象,还可以创建自定义分页用户界面。在 TemplatePagerField 模板中,可以使用 Container 属性来引用 DataPager 控件。此属性可提供对 DataPager 控件的各个属性的访问。这些属性包括起始行索引、页面大小,以及当前绑定到 ListView 控件的总行数。
对数据进行排序
通过在 Layout Template 模板中添加一个按钮,并将该按钮的 Command Name 属性设置为“Sort”,可以对 List View 控件中显示的数据进行排序。该按钮的 CommandArgument 属性应设置为要用作排序依据的列名。重复单击“Sort”(排序)按钮可在排序方向 Ascending 和 Descending 之间切换。
在“Sort”(排序)按钮的 CommandArgument 属性中,可以指定多个列名。但是,ListView 控件会向整个列表的列应用该排序方向。因此,只有列表的最后一列会应用该排序方向。例如,如果 CommandArgument 包含“LastName, FirstName”,则重复单击“Sort”(排序)按钮会产生某种类似于“LastName, FirstName ASC”或“LastName, FirstName DESC”的表达式。
更多细节请参考文档:
ListView控件.doc (57.00 kb)
40a76bce-889f-4f40-8fce-505d53f1d7b3|0|.0
Tags:
Email2Blog