随笔-312  评论-11907  文章-2  trackbacks-224

 

本文来自《ASP.NET AJAX程序设计——第II卷:客户端Microsoft AJAX Library相关》第9章第3节。

 

9.3 示例程序:实现IDragSourceIDropTarget接口将商品拖放至购物车中

本章第1节介绍了ASP.NET AJAX客户端拖放框架中的DragDropManager对象以及IDragSource和IDropTarget两个重要接口。下面就让我们通过一个简单但却足够完善的示例程序来说明其具体的使用方法。

 

9.3.1 示例程序功能

本示例程序模拟了一个网上商店。程序加载之后将自动从服务器端Web Service中取得当前的商品信息,并显示在页面中。同样显示在页面中的还有用户的购物车。如图9-6所示。

图9-6 网上商店的初始界面

用户可以非常直观地在左侧的商品列表中用鼠标选择并将某种商品拖动到右侧的购物车中,类似于实际生活中在超市购物的场景,如图9-7所示。是不是很酷呢?

图9-7 通过拖动商品到购物车中完成购物过程

在购物车范围内松开鼠标左键,商品即被添加到了购物车中。每拖放一次某商品,购物车中该商品的数量就会加1。图9-8显示了购物车中包含一本《Atlas基础教程》、两本《ASP.NET AJAX程序设计 第I卷》和三本《CSS禅意花园》时的样式。

图9-8 在购物车中添加多个商品

在图9-8中点击购物车中的“Order”按钮,程序将把当前购物车中的商品传回服务器端Web Service中进行处理。然后把Web Service的处理结果显示给用户,如图9-9所示。

图9-9 用服务器端Web Service实现购买功能

 

9.3.2 编写服务器端Web Service

既然程序需要从服务器端取得数据,还需要将购物车中的商品提交回服务器处理,那么处理数据的Web Service定是必不可少的。首先创建一个名为ShoppingService的Web Service:

[System.Web.Script.Services.ScriptService]
public class ShoppingService : System.Web.Services.WebService
{
}

在其中创建一个名为Data的私有属性,表示当前网上商店中的产品集合:

private List<Product> _products;
private List<Product> Products
{
    get
    {
        if (_products == null)
        {
            _products = new List<Product>();
 
            _products.Add(new Product(1, "Atlas基础教程", 39));
            _products.Add(new Product(2, "ASP.NET AJAX程序设计第I卷", 49));
            _products.Add(new Product(3, "ASP.NET AJAX程序设计第II卷", 55));
            _products.Add(new Product(4, "ASP.NET AJAX程序设计第III卷", 39));
            _products.Add(new Product(5, "CSS禅意花园", 49));
        }
        return _products;
    }
}

出于演示的目的,我们并没有查询数据库得到商品集合,而是直接硬编码了几种商品(这些商品都是我已经出版或即将要出版的图书)。在实际开发中,这部分数据通常都需要查询数据库得到。

上述代码中用到的Product类表示一种商品,其定义如下。Id、Name和Price属性分别代表商品的ID、名称和价格:

public class Product
{
    private int _id;
    public int Id
    {
        get { return _id; }
        set { _id = value; }
    }
    
    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
    
    private int _price;
    public int Price
    {
        get { return _price; }
        set { _price = value; }
    }
    
    public Product()
    {
    }
 
    public Product(int id, string name, int price)
    {
        this._id = id;
        this._name = name;
        this._price = price;
    }
}

回到ShoppingService这个Web Service中。编写一个名为GetProducts()的方法,用来返回现有的商品:

[WebMethod]
public Product[] GetProducts()
{
    return Products.ToArray();
}

还需要一个名为Order()的方法,用来处理客户端提交回的购物车中商品的信息,并返回处理结果。注意Order()的方法的参数类型为Dictionary<string, int>,其中每个条目的Key为该商品的Id,Value为购物车中该商品的个数:

[WebMethod]
public string Order(Dictionary<string, int> productsToBeOrdered)
{
    // 商品总数
    int totalQuantity = 0;
    
    // 商品总价格
    int totalPrice = 0;
 
    // 计算商品总数及商品总价格
    foreach (KeyValuePair<string, int> productQuantity in productsToBeOrdered)
    {
        foreach (Product product in Products)
        {
            if (product.Id.ToString() == productQuantity.Key)
            {
                totalQuantity += productQuantity.Value;
                totalPrice += (product.Price * productQuantity.Value);
                break;
            }
        }
    }
    
    // 进行其他处理
    // ......
 
    // 返回客户端处理结果
    return string.Format(
        "You've ordered {0} product(s) and the total price is {1}. Thank you!",
        totalQuantity,
        totalPrice
    );
}

这样即完成了服务器端Web Service的编写。

 

9.3.3 编写DraggableProductBehavior实现可拖动的商品

接下来定义一个名为DraggableProductBehavior的行为,该行为将实现Sys.Preview.UI.IDragSource接口,用来附加到表示产品的DOM元素上并为其提供拖动支持。

新建一个名为ShoppingCart.js的JavaScript文件,先来注册Dflying命名空间:

Type.registerNamespace("Dflying");

然后声明该DraggableProductBehavior的实例字段:

Dflying.DraggableProductBehavior = function(element) {
    // 初始化基类
    Dflying.DraggableProductBehavior.initializeBase(this, [element]);
    
    // 按下鼠标键时的事件处理函数
    this._mouseDownHandler = Function.createDelegate(this, this._handleMouseDown);
    
    // 该可拖动对象所表示的产品
    this._product = null;
    
    // 拖动时跟随鼠标的半透明元素
    this._visual = null;
}

接下来是DraggableProductBehavior的原型定义。篇幅所限,这里不能对代码进行详细解释,请参考其中的注释仔细阅读。需要特别留意的是IDragSource接口中各个方法的实现方式,以及其中粗体部分告知DragDropManager开始拖放操作的语法:

Dflying.DraggableProductBehavior.prototype = {
    // IDragSource接口中的方法
    // 取得该可拖动对象的数据类型——"Product"
    get_dragDataType: function() {
        return "Product";
    },
 
    // 取得该可拖动对象的数据
    getDragData: function(context) {
        return this._product;
    },
 
    // 可拖动对象的拖拽模式——拷贝
    get_dragMode: function() {
        return Sys.Preview.UI.DragMode.Copy;
    },
 
    // 拖动开始时的处理方法
    onDragStart: function() {
    },
 
    // 拖动进行时的处理方法
    onDrag: function() {
    },
 
    // 拖动结束时的处理方法
    onDragEnd: function(canceled) {
        if (this._visual)
            this.get_element().parentNode.removeChild(this._visual);
    },
   
    // product属性
    get_product: function(product) {
        return this._product;
    },
    
    set_product: function(product) {
        this._product = product;
    },
    
    // 初始化方法
    initialize: function() {
        $addHandler(this.get_element(), "mousedown", this._mouseDownHandler);
    },
 
    // mousedown事件处理函数
    _handleMouseDown: function(ev) {
        // DragDropManager需要该项设定
        window._event = ev; 
 
        // 设置拖动时跟随鼠标的半透明元素的样式
        this._visual = this.get_element().cloneNode(true);
        this._visual.style.opacity = "0.7";
        this._visual.style.filter = 
            "progid:DXImageTransform.Microsoft.BasicImage(opacity=0.7)";
        this._visual.style.zIndex = 99999;
        this.get_element().parentNode.appendChild(this._visual);
        var location = Sys.UI.DomElement.getLocation(this.get_element());
        Sys.UI.DomElement.setLocation(this._visual, location.x, location.y);
 
        // 告知DragDropManager开始拖放操作
        Sys.Preview.UI.DragDropManager.startDragDrop(this, this._visual, null);
    },
 
    // 析构方法
    dispose: function() {
        if (this._mouseDownHandler)
            $removeHandler(this.get_element(), "mousedown", this._mouseDownHandler);
        this._mouseDownHandler = null;
        
        Dflying.DraggableProductBehavior.callBaseMethod(this, 'dispose');
    }
}

最后在ASP.NET AJAX客户端框架中注册该DraggableProductBehavior行为。可以看到该行为实现了IDragSource接口:

Dflying.DraggableProductBehavior.registerClass(
    "Dflying.DraggableProductBehavior",
    Sys.UI.Behavior, 
    Sys.Preview.UI.IDragSource
);

 

9.3.4 编写ShoppingCartBehavior实现可接受商品投放的购物车

依然在ShoppingCart.js这个JavaScript文件中,我们还要定义一个名为ShoppingCartBehavior的行为,该行为将实现Sys.Preview.UI.IDropTarget接口,用来附加到表示购物车的DOM元素上并让其能够接受可拖动对象的投放。

首先声明该ShoppingCartBehavior的实例字段:

Dflying.ShoppingCartBehavior = function(element) {
    // 初始化基类
    Dflying.ShoppingCartBehavior.initializeBase(this, [element]);
    
    // 购物车中的产品列表
    this._products = new Object();
}

接下来是ShoppingCartBehavior的原型定义。同样限于篇幅,这里不一一详细说明。请注意代码中IDropTarget接口中各个方法的实现方式,以及其中粗体部分在DragDropManager中注册/取消注册该投放目标对象的语法:

Dflying.ShoppingCartBehavior.prototype = {
    // IDropTarget接口中的方法
    // 返回购物车元素
    get_dropTargetElement: function() {
        return this.get_element();
    },
 
    // 判断某可拖动元素是否能够投放在该投放目标对象中
    canDrop: function(dragMode, dataType, data) {
        return (dataType == "Product" && data);
    },
 
    // 将某可拖动元素投放在该投放目标对象中
    drop : function(dragMode, dataType, data) {
        if (dataType == "Product" && data) {
            // 购物车中尚无本产品,设置数量为1
            if (this._products[data.Id] == null) {
                this._products[data.Id] = {Product: data, Quantity: 1};
            }
            // 购物车中已经有本产品,将其数量加1
            else {
                this._products[data.Id].Quantity++;
            }
            
            // 刷新购物车的UI
            this._refreshShoppingCart();
            
            // 将购物车背景颜色设置回白色
            this.get_element().style.backgroundColor = "#fff";
        }
    },
 
    // 某可拖动元素位于该投放目标对象中时的处理方法
    onDragEnterTarget : function(dragMode, dataType, data) {
        if (dataType == "Product" && data) {
            // 设置购物车的背景颜色为灰色
            this.get_element().style.backgroundColor = "#E0E0E0";
        }
    },
   
    // 某可拖动元素离开该投放目标对象时的处理方法
    onDragLeaveTarget : function(dragMode, dataType, data) {
        if (dataType == "Product" && data) {
            // 将购物车背景颜色设置回白色
            this.get_element().style.backgroundColor = "#fff";
        }
    },
 
    // 某可拖动元素在该投放目标对象中拖动时的处理方法
    onDragInTarget : function(dragMode, dataType, data) {
    },
   
    // 根据当前购物车中的产品列表刷新购物车的UI
    _refreshShoppingCart: function() {
        var cartBuilder = new Sys.StringBuilder();
        for (var id in this._products) {
            cartBuilder.append("<div>");
            cartBuilder.append(this._products[id].Product.Name);
            cartBuilder.append(" * ");
            cartBuilder.append(this._products[id].Quantity);
            cartBuilder.append("</div>");
        }
        
        this.get_element().innerHTML = cartBuilder.toString();
    },
    
    // 返回表示当前购物车中的产品Id以及数量的对象
    getProductsToBeOrdered: function() {
        var productsToBeOrdered = new Object();
        
        for (var id in this._products) {
            productsToBeOrdered[id] = this._products[id].Quantity;
        }
        
        return productsToBeOrdered;
    },
    
    // 初始化方法
    initialize: function() {
        // 初始化基类
        Dflying.ShoppingCartBehavior.callBaseMethod(this, "initialize");
        
        // 在DragDropManager中注册该投放目标对象
        Sys.Preview.UI.DragDropManager.registerDropTarget(this);
    },
   
    // 析构方法
    dispose: function() {
        // 在DragDropManager中取消注册该投放目标对象
        Sys.Preview.UI.DragDropManager.unregisterDropTarget(this);
        
        Dflying.ShoppingCartBehavior.callBaseMethod(this, "dispose");
    }
}

最后在ASP.NET AJAX客户端框架中注册该ShoppingCartBehavior行为。可以看到该行为实现了IDropTarget接口:

Dflying.ShoppingCartBehavior.registerClass("Dflying.ShoppingCartBehavior",
    Sys.UI.Behavior, Sys.Preview.UI.IDropTarget);

在ShoppingCart.js文件的末尾,不要忘记调用Application对象的notifyScriptLoaded()方法,通知ASP.NET AJAX客户端框架该脚本文件已经顺利加载:

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();

 

9.3.5 编写页面代码

新建一个ASP.NET页面,在其中添加一个ScriptManager控件并引入必要的脚本文件(PreviewScript.js、PreviewDragDrop.js和ShoppingCart.js)以及9.3.2节中编写的Web Service:

<asp:ScriptManager ID="sm" runat="server">
    <Scripts>
        <asp:ScriptReference Assembly="Microsoft.Web.Preview" 
            Name="PreviewScript.js" />
        <asp:ScriptReference Assembly="Microsoft.Web.Preview" 
            Name="PreviewDragDrop.js" />
        <asp:ScriptReference Path="ShoppingCart.js" />
    </Scripts>
    <Services>
        <asp:ServiceReference Path="ShoppingService.asmx" />
    </Services>
</asp:ScriptManager>

然后编写购物车的相关HTML。其中id为shoppingCart的<div />表示购物车元素。id为btnOrder的<input />表示提交订单的按钮:

<div id="shoppingCartContainer">
    <div><strong>Shopping Cart</strong></div>
    <div id="shoppingCart">Drop Products Here...</div>
    <input id="btnOrder" type="button" value="Order" 
        onclick="return btnOrder_onclick()" />
</div>

网站中产品,即可拖动元素的容器相关的HTML非常简单——一个<div />而已。随后我们将在程序运行时根据Web Service返回的商品集合动态创建容器中的各个表示商品的元素:

<h1>Dflying's Books</h1>
<div id="productContainer"></div>

示例程序中购物车和商品列表相关的CSS Class定义如下:

#shoppingCartContainer
{
    float: right; 
    width: 220px; 
    border: 1px solid black;
    margin: 3px;
}
#productContainer div
{
    width: 250px;
    padding: 3px;
    margin: 3px;
    border: 1px solid #666;
    background-color: #fff;
    cursor: move;
}

 

9.3.6 通过Web Service取得商品并显示在页面中

在客户端应用程序初始化之后,我们需要异步调用服务器端Web Service得到商店中产品的信息,并顺便为购物车添加ShoppingCartBehavior行为:

function pageLoad(sender, args) {
    // 调用Web Service得到商店中的产品集合
    ShoppingService.GetProducts(onProductsGot);
    
    // 为购物车添加ShoppingCartBehavior行为
    $create(
        Dflying.ShoppingCartBehavior, 
        {"name": "myShoppingCartBehavior"},
        null, 
        null, 
        $get("shoppingCart")
    );
}

在onProductsGot()回调函数中,我们要根据返回的商品集合动态创建容器中的各个表示商品的元素,并为其一一添加DraggableProductBehavior行为:

function onProductsGot(result) {
    // 获取显示各个产品的容器
    var productContainer = $get("productContainer");
    
    // 遍历服务器端返回的产品集合
    for (var index = 0; index < result.length; ++ index) {
        // 当前产品
        var thisProduct = result[index];
        
        // 根据该产品信息创建DOM元素,并添加到产品容器中
        var productElem = document.createElement("div");
        productElem.innerHTML = thisProduct.Name + " - RMB: "
            + thisProduct.Price;
        productContainer.appendChild(productElem);
        
        // 为该产品添加DraggableProductBehavior行为
        $create(
            Dflying.DraggableProductBehavior, 
            {"product": thisProduct}, // 设置product属性
            null, 
            null, 
            productElem
        );
    }
}

 

9.3.7 将购物车中的商品提交回Web Service处理

当用户点击购物车中的“Order”按钮时,我们需要把购物车中当前的产品信息(包括Id和数量)传回服务器端进行处理。

“Order”按钮的click事件的处理函数如下。其中首先使用Sys.UI.Behavior.getBehaviorByName()方法得到购物车所附加的ShoppingCartBehavior行为,然后取得当前购物车中各个产品的Id和数量,最后将这部分信息回传给Web Service进行处理:

function btnOrder_onclick() {
    // 得到购物车所附加的ShoppingCartBehavior行为
    var shoppingCartBehavior = Sys.UI.Behavior.getBehaviorByName(
        $get("shoppingCart"), 
        "myShoppingCartBehavior"
    );
    
    // 取得当前购物车中各个产品的Id和数量
    var productsToBeOrdered = 
        shoppingCartBehavior.getProductsToBeOrdered();
    
    // 调用Web Service处理订单
    ShoppingService.Order(productsToBeOrdered, onOrdered);
}

在productsToBeOrdered()回调函数中,我们只是简单地使用alert()方法将服务器端的响应提示给用户:

function onOrdered(result) {
    alert(result);
}

 

这样即完成了本示例程序的编写。运行该程序并尝试用这种崭新的拖放方式进行购物,你将看到如图9-6、图9-7、图9-8和图9-9中所示的界面。这种简单直观的购物体验是不是很令人赞叹呢?

在本示例程序中,我们完整地演示了ASP.NET AJAX客户端拖放框架支持的自定义拖放效果的强大功能,以及IDragSource和IDropTarget两个重要接口在拖放全过程中提供的完善的可定制能力。在实际应用中,我们完全可以简单地通过实现这两个接口来实现那些用户梦寐以求的炫目的拖放效果。

posted on 2007-05-29 10:31 Dflying Chen 阅读(7370) 评论(48)  编辑 收藏 所属分类: ASP.NET AJAX (Atlas)

评论:
#1楼  2007-05-29 11:02 | XiaoFaye [未注册用户]
唉。。。B/S无论如何也比不上C/S的。。。。
  回复  引用    
#2楼  2007-05-29 11:06 | Cat Chen      
购物体验是很好,不过开发体验就……感觉还是和RoR有差距,因为这两个接口实在太通用了,需要考虑实现或不实现某个函数,这就太复杂了。

一套系统就一个Shopping Cart,写了那么多代码,貌似服务器端和客户端都设计得很好,然而这些代码是几乎没有机会重用的……除非是写一个通用的购物网站引擎吧,否则为了完成一个有购物功能的网站而这样写就太费力了。然而如果要开发一个通用的Shopping Cart控件,有充足的属性让你对它的方方面面进行定制,那个工作量就只有专业的控件开发企业才承受得起……总的来说,我还是认为个人开发AJAX控件是很痛苦的事情,做了又重用不了。
  回复  引用  查看    
#3楼  2007-05-29 11:06 | 老刘.      
nice~~
正要用。收藏研究:)
  回复  引用  查看    
#4楼  2007-05-29 11:26 | 辉郎      
正点,我正在项目中全面启动企业2.0计划,初步决定使用asp.net ajax
  回复  引用  查看    
#5楼 [楼主] 2007-05-29 12:59 | Dflying Chen      
@XiaoFaye
呵呵,这个当然阿,毕竟BS的历史太“悠久”了
  回复  引用  查看    
#6楼 [楼主] 2007-05-29 13:00 | Dflying Chen      
@Cat Chen
其实关键是没有IDE支持,假如IDE可以自动实现接口,就像C#一样,也不是很难啊,呵呵
  回复  引用  查看    
#7楼 [楼主] 2007-05-29 13:00 | Dflying Chen      
@老刘.
欢迎讨论!
  回复  引用  查看    
#8楼 [楼主] 2007-05-29 13:01 | Dflying Chen      
@辉郎
呵呵,希望常来交流
  回复  引用  查看    
#9楼  2007-05-29 13:18 | Anthan      
Script太多的话开发和维护成本都很高啊。
相比技术,老大更关注成本,郁闷啊...
  回复  引用  查看    
#10楼 [楼主] 2007-05-29 13:19 | Dflying Chen      
@Anthan
是啊,现在的脚本确实比较多…………也没有办法啊……
  回复  引用  查看    
#11楼  2007-05-29 13:27 | Cat Chen      
@Dflying Chen
这是其中重要的一点,不能比较方便地选择override哪个函数,文档暂时也只有英文的。并且要允许自定义扩展也不容易……

举个例子吧,在上述例子中,如果我希望拖放一本书到Cart上面后,Cart上那本书的栏目就有一个小小的Animation,大概就是把书highlight一下的作用,这就无法在不改动原有代码仅仅添加事件的前提下做到。

当然,你可以通过修改ShoppingCartBehavior.drop方法来对外开放这个事件,然而这个事件仅仅是客户端事件,如果你希望做二次开发的人能从服务器端直接定义OnDrop时的Behavior呢?那么问题的复杂度就大大增加了……
  回复  引用  查看    
#12楼  2007-05-30 10:42 | 马可香蕉      
收藏
  回复  引用  查看    
#13楼  2007-05-30 12:22 | ddr888      
好 实在好
能不能多写点asp.net ajax客户端方面的东西 也期待你的新书
  回复  引用  查看    
#14楼  2007-05-30 14:29 | WOW玩家      
要学很多东西呀,而且很难学,没IDE记不了,还是用jQuery算了
  回复  引用  查看    
#15楼  2007-05-30 16:16 | Leepy      
请问,这么多asp.net ajax客户端脚本,该如何去学呢?感觉理解完这个程序,一知半解的
  回复  引用  查看    
#16楼 [楼主] 2007-05-30 16:32 | Dflying Chen      
@Cat Chen
呵呵,其实对于拖放来讲,只提供两个接口肯定是不够的了,不知道ASP.NET AJAX下一步有什么计划,让这个东西更加简单一点。
管靠着Orcas对JavaScript的支持也是不够的
  回复  引用  查看    
#17楼 [楼主] 2007-05-30 16:32 | Dflying Chen      
@马可香蕉
:)
  回复  引用  查看    
#18楼 [楼主] 2007-05-30 16:33 | Dflying Chen      
@ddr888
新书,也就是第二卷中都在讲ASP.NET AJAX客户端框架的东西,个人感觉还是比较系统的,比第一卷中的内容深入不少。我会在Blog上面陆续贴出一些,就像这篇文章一样,希望对您有帮助!
  回复  引用  查看    
#19楼 [楼主] 2007-05-30 16:33 | Dflying Chen      
@WOW玩家
jQuery确实是个不错的东西,开发理念非常巧妙:)
  回复  引用  查看    
#20楼 [楼主] 2007-05-30 16:34 | Dflying Chen      
@Leepy
自吹自擂一下,您可以参考我即将出版的新书《ASP.NET AJAX程序设计&mdash;&mdash;第II卷:客户端Microsoft AJAX Library相关》,里面有详细全面地介绍:
http://www.cnblogs.com/dflying/archive/2007/05/18/751741.aspx
  回复  引用  查看    
#21楼  2007-05-30 16:49 | Leepy      
大哥,让我加入asp.net ajax(atlas)团队吧,我申请了 好像都没消息了!
  回复  引用  查看    
#22楼 [楼主] 2007-05-30 16:54 | Dflying Chen      
@Leepy
已经添加了:)
  回复  引用  查看    
#23楼  2007-05-30 16:58 | Leepy      
请问一下哦
$create(
Dflying.ShoppingCartBehavior,
{"name": "myShoppingCartBehavior1"},
null,
null,
$get("shoppingCart")
);
该如何理解?各个参数代表什么?null表示什么呢?
  回复  引用  查看    
#24楼 [楼主] 2007-05-30 17:08 | Dflying Chen      
@Leepy
Sys.Component.create (type, properties, events, references, element) :

创建某个类型的组件的实例。type表示组件的类型;properties是一个包含组件的属性与属性值的JSON对象;events是一个包含组件的事件与事件处理函数的JSON对象;references是一个包含该组件引用的其他组件的JSON对象;element是与该组件相关联的DOM元素。除了type参数之外,其他所有的参数均可省略。

$create()是其简写形式。
  回复  引用  查看    
#25楼  2007-05-30 17:21 | Leepy      
properties 可以设置多个组件的属性么?如果可以 该如何写?
  回复  引用  查看    
#26楼 [楼主] 2007-05-30 17:26 | Dflying Chen      
@Leepy
properties是一个包含组件的属性与属性值的JSON对象
----------------
{property1: value1, property2: value2}……就是这样的
  回复  引用  查看    
#27楼  2007-05-30 17:40 | Leepy      
DraggableProductBehavior与ShoppingCartBehavior行为是在何时进行初始化的? 是在registerClass(...)之后?还是在$create(...)之后的?
  回复  引用  查看    
#28楼 [楼主] 2007-05-30 17:54 | Dflying Chen      
@Leepy
$create()之后
  回复  引用  查看    
#29楼  2007-05-30 21:44 | picasa [未注册用户]
非常有价值,我下学期正要交ec网站建设。
  回复  引用    
#30楼 [楼主] 2007-05-30 22:39 | Dflying Chen      
@picasa
:)
  回复  引用  查看    
#31楼  2007-05-31 09:52 | Young.J      
@Dflying Chen
请问,asp.net ajax如何像ajaxpro那样直接向客户端返回一个在服务器端定义的对象
  回复  引用  查看    
#32楼  2007-05-31 11:13 | Cat Chen      
@Dflying Chen
我的意思是,任何一个模块都要双端各实现一次,并且最好都开放二次开发接口,这样的工作量实在太大了。

例如简单的搜索功能吧,结果在Repeater中表示。双端各要开发一次的意思是,服务器端要能够根据?q=keyword来筛选数据填充Repeater,客户端要将Repeater输出的HTML识别为客户端控件,再次搜索时为了不整页刷新而通过WebService来搜索并更新改控件。在这里,我们就要为同一个模块实现两次。
  回复  引用  查看    
#33楼  2007-05-31 14:15 | weir      
有源码吗兄弟
  回复  引用  查看    
#34楼  2007-05-31 17:35 | faib      
其实我觉得还是老套点好,一般在每个商品的右边加个按钮,那样所有的人都知道怎么操作了,做的太时尚有时反而不太适合用户。个人意见。
  回复  引用  查看    
#35楼 [楼主] 2007-05-31 19:39 | Dflying Chen      
@Young.J
在Web Method上面加上[ScriptService]属性即可。一般的服务器端对象都能转化
  回复  引用  查看    
#36楼 [楼主] 2007-05-31 19:41 | Dflying Chen      
@Cat Chen
服务器端根据?q=keyword生成一些JavaScript对象,然后随页面发送到客户端即可。客户端可以使用同一个Repeater显示出来啊:)
  回复  引用  查看    
#37楼 [楼主] 2007-05-31 19:41 | Dflying Chen      
@weir
源代码随后将会放出:)
  回复  引用  查看    
#38楼 [楼主] 2007-05-31 19:42 | Dflying Chen      
@faib
恩,你说得对。尊重用户的习惯也非常重要。对于这个拖放实现,我们也可以给出一些提示说明:)
  回复  引用  查看    
#39楼  2007-06-01 09:50 | 仰天一笑      
@Dflying Chen
技术蛮好的,成本挺高的。适合学习,适合放在高档客户需求中,但是感谢你的分享,学习先:)

  回复  引用  查看    
#40楼 [楼主] 2007-06-01 22:50 | Dflying Chen      
@仰天一笑
谢谢支持,有些时候还是挺有用的。
  回复  引用  查看    
#41楼  2007-06-29 07:42 | qzx_ajaxlove [未注册用户]
Dfing Chen :
我把你的源代码重新编译了一下,有错误呀,说是Dflying没有定义。这是什么意思,请赐教!
  回复  引用    
#42楼 [楼主] 2007-07-03 20:49 | Dflying Chen      
@qzx_ajaxlove
十有八九是web.config中的配置问题,先仔细检查一下吧
  回复  引用  查看    
#43楼  2007-07-16 16:28 | renny [未注册用户]
Dflying Chen:

本例的源代码在哪里,我怎么没找到啊,能发一份学习吗,谢谢!

renny@sina.com
  回复  引用    
#44楼 [楼主] 2007-07-17 22:18 | Dflying Chen      
@renny
代码可以在这里下载:http://aspalliance.com/1300
  回复  引用  查看    
#45楼  2007-08-13 20:35 | Benz [未注册用户]
客户端的什么时候出
  回复  引用    
#46楼  2007-10-25 11:30 | yangyi2336 [未注册用户]
谢谢你的例子!!
  回复  引用    
#47楼  2008-04-09 00:01 | 蓝奇高级验证码识别引擎QQ:631753663 [未注册用户]
出售蓝奇高级验证码识别引擎,可准确识别新浪动网淘宝CSDN等多种复杂验证码。

输出为一个标准DLL,可供VB,VC,Delphi,C#.NET,VB.NET,模拟精灵,按键精灵等多平台调用,调用方法简单,几行代码即可完成。独具特色的边缘检测字符分离、旋转倾斜纠正和通用字符匹配算法(无论字体和大小), 使得该引擎对于像新浪、动网、淘宝、CSDN等多种验证码均有不错的识别率,是一款效果较为理想的验证码识别引擎。附详细的调用实例和代码注释等相关技术文档。

官方网站 - http://***/yzm_advocr
识别效果怎么样一试就知道 - DEMO下载 http://***/yzm_advocr/advocr.rar

  回复  引用    

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-05-30 09:14 编辑过


相关链接: