65.9K
CodeProject 正在变化。 阅读更多。
Home

一个完整的 Visual Studio LightSwitch 2013 HTML5 应用程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (36投票s)

2014年3月19日

CPOL

12分钟阅读

viewsIcon

84756

Visual Studio 2013 LightSwitch HTML 5 应用程序教程。

从这里下载项目:

在线演示:

注意:您可以查看一篇关于为该应用程序创建报表的文章,地址是:

在本篇文章中,我们将使用 Visual Studio LightSwitch 创建一个端到端的 HTML 应用程序。目的是展示 LightSwitch 如何帮助您创建专业的业务应用程序,而这些应用程序可能需要开发人员数天才能完成。使用 LightSwitch,您可以在一小时内创建此类应用程序。

您可以在以下地址下载 LightSwitch http://www.microsoft.com/visualstudio/en-us/lightswitch。此外,您还必须安装 Visual Studio 2013(或更高版本)以及 Office Developer Tools for Visual Studio 2013 – March 2014 Update(或更高版本)。

场景

在本例中,我们将负责创建一个满足以下要求的订单跟踪系统应用程序:

  • 产品
    • 添加产品
    • 编辑产品
  • 订单
    • 添加订单
    • 编辑订单
      • 添加订单明细
      • 编辑订单明细
      • 删除订单明细
    • 删除订单
  • Business Rules
    • 允许当前用户仅查看其订单
  • 特点
    • 显示用户的订单数量
    • 显示订单的订单明细数量

image

该应用程序允许您创建 Products(产品)列表。

image

Products(产品)可以被编辑。

image

Orders(订单)可以被创建。

image

一个 Order(订单)包含多个 Order Details(订单明细)。

image

一个 Order Detail(订单明细)包含一个 Product(产品),从可用 Products(产品)列表中选择,以及一个 quantity(数量)。

创建应用程序

image

打开 Visual Studio 并选择 文件,然后选择 新建项目

image

创建一个新的 LightSwitch HTML 应用程序

image

应用程序将被创建。

image

应用程序将显示在 解决方案资源管理器中。

image

Server(服务器)项目中的 数据源 文件夹上右键单击,然后选择 添加表

image

单击表名进行编辑。

将表名更改为 Product(产品)。

image

此外,为该表添加 ProductName(产品名称)和 ProductPrice(产品价格)字段。

image

单击“保存”按钮保存该表。

image

创建一个 Order(订单)表(包含上图中的字段)。

image

创建一个 OrderDetail(订单明细)表(包含上图中的字段)。

创建关系

当表相关联时,您将始终希望建立关系。这允许最优化的 LightSwitch 应用程序构建。在创建查询时,定义了关系后,您只需键入一个句点(“.”)即可从一个实体遍历到另一个实体。这节省了大量编码工作并减少了编码错误。

在创建用户界面时,定义关系可以为您节省大量编码工作,因为 LightSwitch 可以自动将例如 Order Details(订单明细)与其关联的 Order(订单)关联起来。

image

单击 关系 按钮,在 OrderDetail(订单明细)和 Product(产品)表之间创建关系

image

会出现一个框。选择 Product(产品)作为表,然后单击 确定(确保其他字段与上图匹配)。

image

您将看到已创建关系。您可以双击该线条来编辑关系。

image

再次单击 关系 按钮,并与 Order(订单)表建立关系。

创建过滤器

我们需要实现的一项功能是只显示用户自己的订单(并允许管理员查看所有订单)。我们必须记住,所有 LightSwitch 应用程序 都通过 OData 公开所有数据,因此我们必须始终在服务器端代码中设置安全,而不仅仅是在客户端代码(例如 HTMLSilverlight LightSwitch 客户端)中。

image

我们需要做的第一件事是启用安全性。

image

接下来,我们打开 Orders(订单)表,选择 编写代码,然后选择 Orders_Filter

为该方法使用以下代码

        partial void Orders_Filter(ref Expression<Func<Order, bool>> filter)
        {
            // Only show the Orders for the current user
            filter = (x => x.UserName == this.Application.User.Name);
        }

所有访问此表的数据都将通过此过滤器。

设置默认值

考虑到我们必须在服务器端代码中设置所有与安全相关的内容,我们意识到使用当前用户的 UserName(用户名)标记订单必须使用服务器端代码来设置,以防止 UserName(用户名)被不正确地设置。

image

打开 Orders(订单)表,选择 编写代码,然后选择 Orders_Inserting。为该方法使用以下代码

         partial void Orders_Inserting(Order entity)
        {
            // Set the Username 
            entity.UserName = this.Application.User.Name;
        }

Orders_Updating 事件执行相同的操作。

稍后,我们也将使用客户端代码设置 UserName(用户名),但服务器端代码将始终运行并覆盖任何客户端设置的值。

创建查询

我们需要实现的另一项功能是显示当前用户的订单数量。我们将创建一个稍后可以从客户端使用的查询。

image

右键单击 Orders(订单)表,然后选择 添加查询

image

通过单击标题并进行编辑,将查询命名为 OrdersForUser(用户订单)。先保存它,然后选择 OrdersForUser PreprocessQuery

为该方法使用以下代码

        partial void OrdersForUser_PreprocessQuery(ref IQueryable<Order> query)
        {
            // Only show the Orders for the current user
            query = query.Where(x => x.UserName == this.Application.User.Name);
        }

创建产品用户界面

image

我们首先创建一个屏幕,允许我们查看 Products(产品)。

解决方案资源管理器中右键单击 Client(客户端)节点,然后选择 添加屏幕

image

使用 Products(产品)表创建一个 通用屏幕集

image

屏幕将被创建。

image

F5 运行应用程序。

注意:在调试时,您将自动以 TestUser(测试用户)身份登录。

image

单击 添加 按钮来添加一个 Product(产品)。

image

添加一个产品,然后单击 保存 按钮来保存它。

image

Product(产品)将显示在一个列表中。

单击 Product(产品)以在详细信息视图屏幕中显示它。

image

单击 编辑 按钮来编辑记录。

单击浏览器后退按钮返回上一页。

创建主页

image

现在我们将创建 屏幕。

右键单击 Screens(屏幕)文件夹,然后选择 添加屏幕…

image

创建一个名为 Main(主)的新屏幕,使用 Orders(订单)表作为 屏幕数据

image

我们想做的第一件事是当用户单击列表中的 Order(订单)时打开一个新屏幕。

单击 磁贴列表控件,然后在控件的属性中选择项目点击操作。

image

编辑项目点击操作对话框打开时,将屏幕连接到一个编辑屏幕。

选择 选择现有方法

选择 Orders.editSelected

对于 导航至,选择 (新屏幕…),然后单击 确定

image

将显示 添加新屏幕框。选择 订单明细订单明细,然后单击 确定

image

页面上,我们需要添加一个按钮来创建新 Order(订单)。

打开 页面的 命令栏,然后单击添加按钮,创建到 AddEditOrder(添加/编辑订单)页面的链接(处于添加模式)。

image

右键单击 屏幕,然后选择 设置为首页,这样它将是我们运行应用程序时首先出现的屏幕。

查看到目前为止的应用程序…

image

运行应用程序。

image

我们看到可以使用下拉菜单导航到 产品页面。

image

当我们单击 添加订单按钮打开 添加/编辑订单对话框时,用户名并未为我们填写(也应该是只读的)。

订单日期也应设置为当前日期作为其默认值。

image

当我们切换到 订单明细选项卡时,我们没有添加 订单明细的按钮。

关闭网页浏览器,返回 Visual Studio

创建订单明细编辑屏幕

image

为了允许我们创建和编辑 订单明细记录,打开 AddEditOrder(添加/编辑订单)屏幕,在 订单明细(选项卡)下,选择 命令栏下的添加

选择 OrderDetails(订单明细)集合的 addAndEditNew(添加并编辑新项)方法,以及 (新屏幕) 作为 导航至

image

添加新屏幕对话框显示时,选择 订单明细详细信息作为 要包含的其他数据

image

AddEditOrderDetail(添加/编辑订单明细)屏幕打开时,右键单击包含 Order(订单)下拉菜单的行布局,并删除它。

我们不需要显示 Order(订单)(并允许其更改),因为它将在用户到达此屏幕时设置好。

image

我们将创建一个按钮来允许用户编辑 订单明细

返回 AddEditOrder(添加/编辑订单)屏幕。

单击 OrderDetails(订单明细) 磁贴列表,然后在属性中选择项目点击事件。

编辑项目点击操作对话框中,选择 OrderDetails.editSelected(订单明细.编辑选中项)以及 导航至:添加/编辑订单明细(您在上一步创建的屏幕)。

image

当我们运行应用程序时,现在有了一个 添加订单明细的按钮。

image

我们可以单击 产品框中的带圆圈的加号图标来查看列表,以便选择一个 Product(产品)。

image

然而,当我们创建 订单明细时,我们发现其显示可以改进。

关闭网页浏览器,返回 Visual Studio

格式化订单明细

image

我们回到 添加/编辑订单屏幕,并将 订单明细磁贴列表控件更改为 列表

image

接下来,我们将 列表控件下的 行布局控件更改为 自定义控件

image

自定义控件属性中,我们选择 编辑渲染代码

我们使用以下代码

myapp.AddEditOrder.rows_render = function (element, contentItem) {
    // We need to wait until the Products for the Order Detail are loaded
    // so we create a binding to "value.Product.ProductName"
    // When the data is loaded the binding will be raised
    // We will then have all the data required for our display
    contentItem.dataBind("value.Product.ProductName", function (newValue) {
        // clear the element
        element.innerHTML = "";
        // Create a template
        var itemTemplate = $("<div><div>");
        // Get the Product name and quantity
        var ProductName = contentItem.value.Product.ProductName;
        var ProductQuantity = "";
        if (contentItem.value.Quantity !== undefined) {
            ProductQuantity = ' [' + contentItem.value.Quantity + ']';
        }
        // Create the final display
        var FinalName = $("<h2>").text(ProductName + ProductQuantity);
        // Complete the template
        FinalName.appendTo($(itemTemplate));
        itemTemplate.appendTo($(element));
    });
};

(注意:此代码使用 Promises,有关 Promises 的更多信息,请参阅:在 Visual Studio LightSwitch 中使用 Promises。另请参阅:编写实现 Visual Studio LightSwitch 中绑定模式的 JavaScript)

image

当我们运行应用程序时,输出将按我们期望的方式格式化。

设置默认值

image

如果我们运行应用程序,然后单击 添加订单按钮…

image

…并尝试创建 订单,它将不会保存。

我们缺少 用户名。我们已经添加了代码来用当前用户覆盖 用户名,但由于我们将其设为必填字段,因此仍必须提供。我们可以仅将 用户名字段设为文本框并允许用户输入,但我们可以使用 ServerApplicationContext 来自动在客户端插入它。

请参阅以下文章以获取分步教程:在 LightSwitch HTML 客户端中检索当前用户

使用 Server Application Context

我们现在将创建一个文件处理程序,该处理程序将使用 Server Application Context API 来检索当前登录用户的 用户名。然后,我们将从客户端的 JavaScript 代码调用该处理程序,以填充屏幕上的值。

image

右键单击 Server(服务器)项目,然后选择 添加,然后选择 新建文件夹

创建一个名为 Web 的文件夹。

image

右键单击 Web 文件夹,然后选择 添加,然后选择 新项

image

创建一个名为 GetUserName.ashx 的新 通用处理程序

(注意:您必须从头开始创建文件,以便将正确的引用添加到项目中。如果您仅仅复制粘贴或拖放文件到项目中,它将不起作用。)

为该文件使用以下代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace LightSwitchApplication.Web
{
    public class GetUserName : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            using (var serverContext = ServerApplicationContext.CreateContext())
            {
                context.Response.ContentType = "text/plain";
                context.Response.Write(serverContext.Application.User.Name);
            }
        }
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

image

打开 Order(订单)表,选择 HTML 客户端(选项卡),编写代码,然后选择 created(创建)方法。

为该方法使用以下代码

myapp.Order.created = function (entity) {
    // Set the default date for the Order
    entity.OrderDate = new Date();

    // Using a Promise object we can call the CallGetUserName function
    msls.promiseOperation(CallGetUserName).then(function PromiseSuccess(PromiseResult) {
        // Set the result of the CallGetUserName function to the 
        // UserName of the entity
        entity.UserName = PromiseResult;
    });
};

// This function will be wrapped in a Promise object
function CallGetUserName(operation) {
    $.ajax({
        type: 'post',
        data: {},
        url: '../web/GetUserName.ashx',
        success: operation.code(function AjaxSuccess(AjaxResult) {
            operation.complete(AjaxResult);
        })
    });
}

(注意:有关使用 msls.promiseOperation 的更多信息,请参阅 在 Visual Studio LightSwitch 中使用 Promises。)

image

最后,我们打开 AddEditOrder(添加/编辑订单)屏幕,并将 用户名控件从 文本框更改为 文本标签。

image

当我们运行应用程序时,用户名日期现在在新记录创建时被设置。

您现在将能够创建和保存记录。

调用自定义查询

接下来,我们将调用之前创建的查询,以便显示当前用户的 Orders(订单)数量。

image

打开 屏幕,选择 添加数据项,并创建一个 整数属性。

image

将该属性从 视图模型拖放到屏幕布局上。

image

属性中,将标签设为左对齐

image

要设置该属性的值,请选择 编写代码,然后选择 created(创建)方法。

使用以下代码

myapp.Main.created = function (screen) {
    myapp.activeDataWorkspace.ApplicationData.OrdersForUser().execute().then
        (function (results) {
        var TotalCountOfOrders = CountOrders(results);
        screen.TotalOrdersForCurrentUser = TotalCountOfOrders.toString();
    });
};

function CountOrders(Orders) {
    var TotalOrders = 0;
    var orders = Orders.results;
    orders.forEach(function (order) {
        TotalOrders = TotalOrders + 1;
    });
    return TotalOrders;
}

image

当我们运行应用程序时,我们将看到 Orders(订单)的计数。

调用自定义 JavaScript 查询

image

现在,我们希望在主页上显示 Order(订单)时,显示关联的 订单明细的数量。

首先,我们打开 页面,并删除 磁贴列表中的 用户名创建者字段。

image

Id(ID)字段添加到列表中。

image

将控件更改为 自定义控件

为此控件的 Render(渲染)方法使用以下代码

myapp.Main.Id_render = function (element, contentItem) {
    // Get the current OrderId
    var OrderId = contentItem.value;
    var Int32 = ':Int32';
    // Get all the OrderDetails associated with the current Order
    var filter = '(Order/Id eq ' + msls._toODataString(OrderId, Int32) + ')';
    msls.showProgress(myapp.activeDataWorkspace.ApplicationData.OrderDetails
    .filter(filter)
    .execute()
    .then(function (result) {
        // Loop through each record in the result
        var index = 0;
        var Entities = result.results;
        Entities.forEach(function (entity) {
            // Count the Order Details
            index = index + 1;
        })
        // Set the final output
        var NumberOfOrderDetails = $('<label class=msls-label-text> 
                                   Number of Order Details: ' + index + '</label>');
        NumberOfOrderDetails.appendTo($(element));
    }))
};

image

当我们运行应用程序时,我们将看到 Order(订单)的 订单明细记录的数量。

但是,我们现在注意到,直到页面刷新后,页面上的总计才显示正确的金额。我们可以自动刷新页面…

使用自定义按钮自动刷新页面

image

我们可以通过选择 页面的 磁贴列表项目点击事件,然后选择 编写自己的方法来创建一个自定义按钮。

image

该方法将显示在屏幕设计器左侧的 视图模型中。

右键单击它,然后选择 编辑执行代码

为该方法使用以下代码

myapp.Main.Orders_ItemTap_execute = function (screen) {
    myapp.showAddEditOrder(null, {
        beforeShown: function (addEditOrderScreen) {
            // Set the Order on the AddEditOrder screen
            // to the selected Order on the Main screen
            addEditOrderScreen.Order = screen.Orders.selectedItem;
        },
        afterClosed: function (addEditScreen, navigationAction) {
            // If the user commits the change,
            // update the selected order on the Main screen
            if (navigationAction === msls.NavigateBackAction.commit) {
                // *****************************************
                // Refresh the Orders
                screen.Orders.load();
            }
        }
    });
};

image

编辑记录后,总计会自动更新。

删除记录

image

打开 添加/编辑订单明细屏幕,并向 命令栏添加一个按钮。

为该按钮创建一个 删除方法。

image

右键单击 视图模型中的 Delete(删除)方法,然后选择 编辑执行代码

为该方法使用以下代码

myapp.AddEditOrderDetail.Delete_execute = function (screen) {
    screen.OrderDetail.deleteEntity();
    return myapp.commitChanges().then(null, function fail(e) {
        myapp.cancelChanges();
        throw e;
    });
};

image

在编辑 订单明细时,删除按钮现在将显示。

image

您将需要单击 添加/编辑订单页面上的 保存按钮来提交更改。

我们还可以使用以下代码向 添加/编辑订单屏幕添加一个 删除按钮

myapp.AddEditOrder.Delete_execute = function (screen) {
    screen.Order.deleteEntity();
    myapp.commitChanges().then(null, function fail(e) {
        msls.showMessageBox(e.message, {
            title: "Error",
            buttons: msls.MessageBoxButtons.ok
        }).then(function (result) {
            if (result === msls.MessageBoxResult.ok) {
                // Discard Changes
                screen.details.dataWorkspace.ApplicationData
                    .details.discardChanges();
            }
        });
    });
};

image

您会注意到,如果我们尝试删除仍有 订单明细记录的 Order(订单)…

image

…它将引发错误,因为我们之前在表之间创建的关系设置为不允许在存在关联记录的情况下删除 Order(订单)。

请先删除所有 Order Details(订单明细),然后您就可以删除 Order(订单)。

LightSwitch 帮助网站文章

LightSwitch 团队 HTML 和 JavaScript 文章

历史

  • 2014 年 8 月 24 日:初始版本
© . All rights reserved.