博客 (18)

打开 appsettings.json,添加一项配置(如下方示例中的“SiteOptions”项)

image.png

* 注意,如需配置开发环境与生产环境不同的值,可单独在 appsettings.Development.json 文件中配置不同项,格式层次须一致;


C# 中习惯用强类型的方式来操作对象,那么在项目根目录添加类(类名以 SiteOptions为例),格式与 appsettings.json 中保持一致:

public class SiteOptions
{
    public ERPOptions ERP { get; set; }
    public WeixinOpenOptions WeixinOpen { get; set; }
    public WeixinMPOptions WeixinMP { get; set; }
    public SMSOptions SMS { get; set; }
    public AliyunOSSOptions AliyunOSS { get; set; }

    /// <summary>
    /// 单个文件上传的最大大小(MB)
    /// </summary>
    public int MaxSizeOfSigleFile_MB { get; set; }

    /// <summary>
    /// 单个文件上传的最大大小(字节)
    /// </summary>
    public int MaxSizeOfSigleFile_B => MaxSizeOfSigleFile_MB * 1024 * 1024;

    public class ERPOptions
    {
        public int ChannelId { get; set; }
        public string AppKey { get; set; }
    }
    public class WeixinOpenOptions
    {
        public string AppId { get; set; }
        public string AppSecret { get; set; }
    }
    public class WeixinMPOptions
    {
        public string AppId { get; set; }
        public string AppSecret { get; set; }
    }
    public class SMSOptions
    {
        public string AppKey { get; set; }
    }
    public class AliyunOSSOptions
    {
        public string Endpoint { get; set; }
        public string AccessKeyId { get; set; }
        public string AccessKeySecret { get; set; }
        public string BucketName { get; set; }

        /// <summary>
        /// 格式://域名/
        /// </summary>
        public string CdnUrl { get; set; }
    }
}


在 Startup 中注入 IConfiguration,并在 ConfigureServices() 方法中添加服务(注意使用 GetSection() 映射到自命名的“SiteOptions”项)

image.png


在控制器中使用

在控制器类中键入“ctor”,并按两次 Tab 键,创建构造函数

image.png

在构造函数中注入“IOptions”,并在 Action 中使用

using Microsoft.Extensions.Options;

public class TestController : Controller
{
    private readonly IOptions<SiteOptions> options;

    public TestController(IOptions<SiteOptions> options)
    {
        this.options = options;
    }

    public IActionResult Index()
    {
        return View(options.Value.ERP.ChannelId.ToString());
    }
}


在视图中使用

@using Microsoft.Extensions.Options
@inject IOptions<SiteOptions> options

@options.Value.ERP.ChannelId


xoyozo 5 年前
3,391

获取控制器(Controller)名称

控制器的 Action 中

RouteData.Values["controller"].ToString()


RouteData.Route.GetRouteData(HttpContext).Values["controller"].ToString()


视图中

ViewContext.RouteData.Values["controller"].ToString()


ViewContext.RouteData.Route.GetRouteData(Context).Values["controller"].ToString()


公共方法中

HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString()


过滤器中

以 ActionFilterAttribute 为例,实现一个继承类,重写相关方法,在重写的方法中获取控制器名称

/// <summary>
/// 可用于检查用户是否已经登录(在 Action 之前执行)
/// </summary>
/// <param name="filterContext"></param>
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    base.OnActionExecuting(filterContext);
    string controller = filterContext.RouteData.Values["controller"].ToString();
}


获取 Action 名称

将以上代码中的 "controller" 替换成 "action" 即可获取 Action 名称。

获取区域(Area)名称

控制器的 Actione 中

RouteData.DataTokens["area"]?.ToString()

注意:应使用空传播运算符

获取所有 Action 参数

RouteData.Values
转自 邵雷 5 年前
3,807

传统的 LIKE 模糊查询(前置百分号)无法利用索引,特别是多个关键词 OR,或在多个字段中 LIKE,更是效率低下。本文研究对文章进行分词以提高检索的准确度和查询效率。


根据自己的编程语言选择一款合适的中文分词组件,我在 ASP.NET 平台下选择了 jieba.NET。


设想的步骤:

  1. 分别对文章标题、标签、正文进行分词,保存到一张分词表上。该表把“文章 ID”和“词语”设为联合主键,用 3 个字段记录该词语分别在标题、标签、正文中出现的次数,另外还可以按需要添加文章分类 ID、文章创建时间等字段。

  2. 当用户输入关键词进行检索时,先将关键词分词,在分词表中用 in 语法查询到所有相关的记录;

  3. 使用 group by 语法对查询结果按文章 ID 分组;

  4. 关键在排序上,理想的排序是:

    a. 先按搜索关键词中不同词语的出现量排序,即:若搜索关键词分词后是 3 个词语,那么全部包含这 3 个词的文章优先,只匹配其中 2 个词语的其次;

    b. 再按搜索关键词在文中累计出现的次数排序(考虑权重),即:我们先假定标题和标签的分词权重为 5(意思是一个分词在标题中出现 1 次相当于在正文中出现 5 次),那么累加每个分词在标题、标签、正文的权重次数,得分高的优先;

    c. 再进一步考虑文章的发布时间,即将文章的发布时间距离最早一篇文章的发布时间(或一个较早的固定日期)相隔的天数,乘以一个系数加入到权重中,这个系数按不同文章分类(场景)不同,比如新闻类的大一点,情感类的小一点)。乘以系数时一篇文章只加权一次,不要加权到每个分词。

    d. 根据需求还可以加入文章热度(阅读数)的权重。


根据上述逻辑对一个有 18 万篇文章的内容管理系统进行改造,循环所有文章进行分词统计,得到一张包含 5 千万条记录的分词表(系统中部分文章只有标题、标签和外链,没有正文,否则更多)。

由于查询中包含 in、group by、count、sum、运算等,再若分类是无级限的,即文章分类 ID 也是 in 查询,然后分页,即使创建索引,效率也只能呵呵了。


简化:

不对正文进行分词;

不按权重进行排序;


那么分词表的记录数降到 250 万条,同样用 in 查询分词,先按搜索关键词中不同词语的出现量排序,再按发布时间排序,分页后获得一页的文章 ID 集合,再去文章表中 in 获取详细信息(注意保持一页中的排序)。

添加相关索引后,查询一个包含 3 个分词的关键词仅需十几毫秒。因为 in 的内容比较离散,所以索引的利用率比较高。



xoyozo 6 年前
4,397

当使用在线编辑器编辑一篇文章(或从 Word 复制)后,会得到包含 HTML 标签的字符串内容,可以直接将它输出到页面上而不需要进行 HTML 编码。

但是,当我们需要改变图片大小时,我们发现有些图片的尺寸是直接使用 style 属性固定的,除了用 JS 进行后期处理,我们可以在服务端对 <img /> 进行修正。

这个场景会在小程序开发的时候遇到。

我们可以在客户端用 JS 进行处理,也可以在服务端用类似的方法处理(使用正则表达式)。参此文

这里使用 HtmlAgilityPack 通过递归节点来处理:

/// <summary>
/// 给所有指定节点添加样式
/// </summary>
/// <param name="html"></param>
/// <param name="tag">节点名称(小写),如:img</param>
/// <param name="styles">要添加的样式,如:max-width:100%;</param>
/// <returns></returns>
public static string AddStyleToHtmlNode(string html, string tag, string styles)
{
    HtmlDocument doc = new HtmlDocument();
    doc.LoadHtml(html);

    for (var i = 0; i < doc.DocumentNode.ChildNodes.Count; i++)
    {
        doc.DocumentNode.ChildNodes[i] = AddStyleToHtmlNode(doc.DocumentNode.ChildNodes[i], tag, styles);
    }

    return doc.DocumentNode.OuterHtml;
}
private static HtmlNode AddStyleToHtmlNode(HtmlNode node, string tag, string styles)
{
    if (node.Name == tag)
    {
        var style = node.GetAttributeValue("style", null);
        node.SetAttributeValue("style", ((string.IsNullOrWhiteSpace(style) ? "" : style.Trim() + ";") + styles).Replace(";;", ";"));
    }
    for (var i = 0; i < node.ChildNodes.Count; i++)
    {
        node.ChildNodes[i] = AddStyleToHtmlNode(node.ChildNodes[i], tag, styles);
    }
    return node;
}

直接调用:

Content = zStringHTML_190126.AddStyleToHtmlNode(Content, "img", "max-width:100%;height:auto;");


xoyozo 6 年前
4,599

函数功能:添加/修改/删除/获取 URL 中的参数(锚点敏感)

/// <summary>
/// 设置 URL 参数(设 value 为 undefined 或 null 删除该参数)
/// <param name="url">URL</param>
/// <param name="key">参数名</param>
/// <param name="value">参数值</param>
/// </summary>
function fn_set_url_param(url, key, value) {
    // 第一步:分离锚点
    var anchor = "";
    var anchor_index = url.indexOf("#");

    if (anchor_index >= 0) {
        anchor = url.substr(anchor_index);
        url = url.substr(0, anchor_index);
    }

    // 第二步:删除参数
    key = encodeURIComponent(key);
    var patt;

    // &key=value
    patt = new RegExp("\\&" + key + "=[^&]*", "gi");
    url = url.replace(patt, "");

    // ?key=value&okey=value  -> ?okey=value
    patt = new RegExp("\\?" + key + "=[^&]*\\&", "gi");
    url = url.replace(patt, "?");

    // ?key=value
    patt = new RegExp("\\?" + key + "=[^&]*$", "gi");
    url = url.replace(patt, "");

    // 第三步:追加参数
    if (value != undefined && value != null) {
        value = encodeURIComponent(value);
        url += (url.indexOf("?") >= 0 ? "&" : "?") + key + "=" + value;
    }

    // 第四步:连接锚点
    url += anchor;

    return url;
}

/// <summary>
/// 获取 URL 参数(无此参数返回 null,多次匹配使用“,”连接)
/// <param name="url">URL</param>
/// <param name="key">参数名</param>
/// </summary>
function fn_get_url_param(url, key) {
    key = encodeURIComponent(key);
    var patt = new RegExp("[?&]" + key + "=([^&#]*)", "gi");

    var values = [];

    while ((result = patt.exec(url)) != null) {
        values.push(decodeURIComponent(result[1]));
    }

    if (values.length > 0) {
        return values.join(",");
    } else {
        return null;
    }
}


调用示例:

var url = window.location.href;

// 设置参数
url = fn_set_url_param(url, 'a', 123);

// 获取参数
console.log(fn_get_url_param, url, 'a');


压缩版:

function fn_set_url_param(b,c,e){var a="";var f=b.indexOf("#");if(f>=0){a=b.substr(f);b=b.substr(0,f)}c=encodeURIComponent(c);var d;d=new RegExp("\\&"+c+"=[^&]*","gi");b=b.replace(d,"");d=new RegExp("\\?"+c+"=[^&]*\\&","gi");b=b.replace(d,"?");d=new RegExp("\\?"+c+"=[^&]*$","gi");b=b.replace(d,"");if(e!=undefined&&e!=null){e=encodeURIComponent(e);b+=(b.indexOf("?")>=0?"&":"?")+c+"="+e}b+=a;return b}
function fn_get_url_param(b,c){c=encodeURIComponent(c);var d=new RegExp("[?&]"+c+"=([^&#]*)","gi");var a=[];while((result=d.exec(b))!=null){a.push(decodeURIComponent(result[1]))}if(a.length>0){return a.join(",")}else{return null}};


xoyozo 7 年前
3,487

http://npoi.codeplex.com/documentation

免费,开源,无需安装 Office,功能强大,兼容性好,使用方便,可以在 Visual Studio 的 NuGet 管理器中直接搜索安装。

导出 Excel 简单示例:

HSSFWorkbook book = new HSSFWorkbook();
ISheet sheet = book.CreateSheet("工作表1");

IRow r0 = sheet.CreateRow(0);
r0.CreateCell(0).SetCellValue("行1列1");
r0.CreateCell(1).SetCellValue("行1列2");

IRow r1 = sheet.CreateRow(1);
r1.CreateCell(0).SetCellValue("行2列1");
r1.CreateCell(2).SetCellValue("行2列3");

MemoryStream ms = new MemoryStream();
book.Write(ms);
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xls", "文件名"));
Response.BinaryWrite(ms.ToArray());
Response.End();
book = null;
ms.Close();
ms.Dispose();

字体相关:

ICellStyle style = book.CreateCellStyle();
IFont font = book.CreateFont();
font.FontHeightInPoints = 20; // 字体大小
font.Color = HSSFColor.White.Index; // 字体颜色
style.SetFont(font);
style.FillForegroundColor = HSSFColor.Red.Index; // 背景色
style.FillPattern = FillPattern.SolidForeground;
cell.CellStyle = style;

合并单元格:

CellRangeAddress cra = new CellRangeAddress(r - 1, r - 1, c - 1, c);
sheet.AddMergedRegion(cra);

宽度自适应:

for (int i = 1; i < c; i++) {
  sheet.AutoSizeColumn(i);
}

函数:

cell.SetCellFormula("SUM(B2:B4)");

顺便提一句,ICellStyle 和 IFont 最好一种样式一个变量先定义好再用,不要在循环里疯狂地 Create,否则超出数量(512个)会导致样式失效。

其它参考:http://www.ez2o.com/Blog/Post/csharp-Excel-NPOI-Font-Style

 

 

xoyozo 8 年前
6,183

我们继续讲解LINQ to SQL语句,这篇我们来讨论Group By/Having操作符和Exists/In/Any/All/Contains操作符。

Group By/Having操作符

适用场景:分组数据,为我们查找数据缩小范围。

说明:分配并返回对传入参数进行分组操作后的可枚举对象。分组;延迟

1.简单形式:

var q =
    from p in db.Products
    group p by p.CategoryID into g
    select g;

语句描述:使用Group By按CategoryID划分产品。

说明:from p in db.Products 表示从表中将产品对象取出来。group p by p.CategoryID into g表示对p按CategoryID字段归类。其结果命名为g,一旦重新命名,p的作用域就结束了,所以,最后select时,只能select g。当然,也不必重新命名可以这样写:

var q =
    from p in db.Products
    group p by p.CategoryID;

我们用示意图表示:

GroupBy分组统计示意图

如果想遍历某类别中所有记录,这样:

foreach (var gp in q)
{
    if (gp.Key == 2)
    {
        foreach (var item in gp)
        {
            //do something
        }
    }
}

2.Select匿名类:

var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new { CategoryID = g.Key, g }; 

说明:在这句LINQ语句中,有2个property:CategoryID和g。这个匿名类,其实质是对返回结果集重新进行了包装。把g的property封装成一个完整的分组。如下图所示:

GroupBy分组匿名类示意图

如果想遍历某匿名类中所有记录,要这么做:

foreach (var gp in q)
{
    if (gp.CategoryID == 2)
    {
        foreach (var item in gp.g)
        {
            //do something
        }
    }
}

3.最大值

var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new {
        g.Key,
        MaxPrice = g.Max(p => p.UnitPrice)
    };

语句描述:使用Group By和Max查找每个CategoryID的最高单价。

说明:先按CategoryID归类,判断各个分类产品中单价最大的Products。取出CategoryID值,并把UnitPrice值赋给MaxPrice。

4.最小值

var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new {
        g.Key,
        MinPrice = g.Min(p => p.UnitPrice)
    };

语句描述:使用Group By和Min查找每个CategoryID的最低单价。

说明:先按CategoryID归类,判断各个分类产品中单价最小的Products。取出CategoryID值,并把UnitPrice值赋给MinPrice。

5.平均值

var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new {
        g.Key,
        AveragePrice = g.Average(p => p.UnitPrice)
    };

语句描述:使用Group By和Average得到每个CategoryID的平均单价。

说明:先按CategoryID归类,取出CategoryID值和各个分类产品中单价的平均值。

6.求和

var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new {
        g.Key,
        TotalPrice = g.Sum(p => p.UnitPrice)
    };

语句描述:使用Group By和Sum得到每个CategoryID 的单价总计。

说明:先按CategoryID归类,取出CategoryID值和各个分类产品中单价的总和。

7.计数

var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new {
        g.Key,
        NumProducts = g.Count()
    };

语句描述:使用Group By和Count得到每个CategoryID中产品的数量。

说明:先按CategoryID归类,取出CategoryID值和各个分类产品的数量。

8.带条件计数

var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new {
        g.Key,
        NumProducts = g.Count(p => p.Discontinued)
    };

语句描述:使用Group By和Count得到每个CategoryID中断货产品的数量。

说明:先按CategoryID归类,取出CategoryID值和各个分类产品的断货数量。 Count函数里,使用了Lambda表达式,Lambda表达式中的p,代表这个组里的一个元素或对象,即某一个产品。

9.Where限制

var q =
    from p in db.Products
    group p by p.CategoryID into g
    where g.Count() >= 10
    select new {
        g.Key,
        ProductCount = g.Count()
    };

语句描述:根据产品的―ID分组,查询产品数量大于10的ID和产品数量。这个示例在Group By子句后使用Where子句查找所有至少有10种产品的类别。

说明:在翻译成SQL语句时,在最外层嵌套了Where条件。

10.多列(Multiple Columns)

var categories =
    from p in db.Products
    group p by new
    {
        p.CategoryID,
        p.SupplierID
    }
        into g
        select new
            {
                g.Key,
                g
            };

语句描述:使用Group By按CategoryID和SupplierID将产品分组。

说明: 既按产品的分类,又按供应商分类。在by后面,new出来一个匿名类。这里,Key其实质是一个类的对象,Key包含两个Property:CategoryID、SupplierID。用g.Key.CategoryID可以遍历CategoryID的值。

11.表达式(Expression)

var categories =
    from p in db.Products
    group p by new { Criterion = p.UnitPrice > 10 } into g
    select g;

语句描述:使用Group By返回两个产品序列。第一个序列包含单价大于10的产品。第二个序列包含单价小于或等于10的产品。

说明:按产品单价是否大于10分类。其结果分为两类,大于的是一类,小于及等于为另一类。

Exists/In/Any/All/Contains操作符

适用场景:用于判断集合中元素,进一步缩小范围。

Any

说明:用于判断集合中是否有元素满足某一条件;不延迟。(若条件为空,则集合只要不为空就返回True,否则为False)。有2种形式,分别为简单形式和带条件形式。

1.简单形式:

仅返回没有订单的客户:

var q =
    from c in db.Customers
    where !c.Orders.Any()
    select c;

生成SQL语句为:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName],
[t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region],
[t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE NOT (EXISTS(
    SELECT NULL AS [EMPTY] FROM [dbo].[Orders] AS [t1]
    WHERE [t1].[CustomerID] = [t0].[CustomerID]
   ))

2.带条件形式:

仅返回至少有一种产品断货的类别:

var q =
    from c in db.Categories
    where c.Products.Any(p => p.Discontinued)
    select c;

生成SQL语句为:

SELECT [t0].[CategoryID], [t0].[CategoryName], [t0].[Description],
[t0].[Picture] FROM [dbo].[Categories] AS [t0]
WHERE EXISTS(
    SELECT NULL AS [EMPTY] FROM [dbo].[Products] AS [t1]
    WHERE ([t1].[Discontinued] = 1) AND 
    ([t1].[CategoryID] = [t0].[CategoryID])
    )

All

说明:用于判断集合中所有元素是否都满足某一条件;不延迟

1.带条件形式

var q =
    from c in db.Customers
    where c.Orders.All(o => o.ShipCity == c.City)
    select c;

语句描述:这个例子返回所有订单都运往其所在城市的客户或未下订单的客户。

Contains

说明:用于判断集合中是否包含有某一元素;不延迟。它是对两个序列进行连接操作的。

string[] customerID_Set =
    new string[] { "AROUT", "BOLID", "FISSA" };
var q = (
    from o in db.Orders
    where customerID_Set.Contains(o.CustomerID)
    select o).ToList();

语句描述:查找"AROUT", "BOLID" 和 "FISSA" 这三个客户的订单。 先定义了一个数组,在LINQ to SQL中使用Contains,数组中包含了所有的CustomerID,即返回结果中,所有的CustomerID都在这个集合内。也就是in。 你也可以把数组的定义放在LINQ to SQL语句里。比如:

var q = (
    from o in db.Orders
    where (
    new string[] { "AROUT", "BOLID", "FISSA" })
    .Contains(o.CustomerID)
    select o).ToList();

Not Contains则取反:

var q = (
    from o in db.Orders
    where !(
    new string[] { "AROUT", "BOLID", "FISSA" })
    .Contains(o.CustomerID)
    select o).ToList();

1.包含一个对象:

var order = (from o in db.Orders
             where o.OrderID == 10248
             select o).First();
var q = db.Customers.Where(p => p.Orders.Contains(order)).ToList();
foreach (var cust in q)
{
    foreach (var ord in cust.Orders)
    {
        //do something
    }
}

语句描述:这个例子使用Contain查找哪个客户包含OrderID为10248的订单。

2.包含多个值:

string[] cities = 
    new string[] { "Seattle", "London", "Vancouver", "Paris" };
var q = db.Customers.Where(p=>cities.Contains(p.City)).ToList();

语句描述:这个例子使用Contains查找其所在城市为西雅图、伦敦、巴黎或温哥华的客户。

总结一下这篇我们说明了以下语句:

Group By/Having 分组数据;延迟
Any 用于判断集合中是否有元素满足某一条件;不延迟
All 用于判断集合中所有元素是否都满足某一条件;不延迟
Contains 用于判断集合中是否包含有某一元素;不延迟

本系列链接:LINQ体验系列文章导航

LINQ推荐资源

LINQ专题:http://kb.cnblogs.com/zt/linq/ 关于LINQ方方面面的入门、进阶、深入的文章。
LINQ小组:http://space.cnblogs.com/group/linq/ 学习中遇到什么问题或者疑问提问的好地方。

转自 李永京 16 年前
4,295

CatalogEdit.aspx

<asp:ListBox ID="ListBox1" runat="server" DataSourceID="SqlDataSource1" DataTextField="catalog"
DataValueField="ID" Rows="10"></asp:ListBox>
<asp:LinkButton ID="LinkButton_up" runat="server" OnClick="LinkButton_up_Click">上移</asp:LinkButton>
<asp:LinkButton ID="LinkButton_down" runat="server" OnClick="LinkButton_down_Click">下移</asp:LinkButton>
<asp:LinkButton ID="LinkButton_del" runat="server" OnClick="LinkButton_del_Click">删除</asp:LinkButton>
<asp:Label ID="Label_alert" runat="server" ForeColor="Red" Text="Label"></asp:Label><br />
<asp:TextBox ID="TextBox_newCatalog" runat="server"></asp:TextBox>
<asp:LinkButton ID="LinkButton_add" runat="server" OnClick="LinkButton_add_Click">新增</asp:LinkButton>
<asp:LinkButton ID="LinkButton_edit" runat="server" OnClick="LinkButton_edit_Click">修改</asp:LinkButton>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionStringLink %>"
DeleteCommand="DELETE FROM [xLinkCategory] WHERE [ID] = ?" InsertCommand="INSERT INTO [xLinkCategory] ([username],[catalog],[order]) VALUES (?,?,0)"
ProviderName="<%$ ConnectionStrings:ConnectionStringLink.ProviderName %>"
SelectCommand="SELECT [ID], [catalog] FROM [xLinkCategory] WHERE ([username] = ?) ORDER BY [order],[ID] desc"
UpdateCommand="UPDATE [xLinkCategory] SET [catalog] = ? WHERE [ID] = ?">
<DeleteParameters>
<asp:Parameter Name="ID" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="catalog" Type="String" />
<asp:Parameter Name="ID" Type="Int32" />
</UpdateParameters>
<SelectParameters>
<asp:SessionParameter Name="username" SessionField="username" Type="String" />
</SelectParameters>
<InsertParameters>
<asp:SessionParameter Name="username" SessionField="username" Type="String" />
<asp:Parameter Name="catalog" Type="String" />
</InsertParameters>
</asp:SqlDataSource>

CatalogEdit.aspx.cs

/**//// <summary>
/// 上移
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void LinkButton_up_Click(object sender, EventArgs e)
{
if (ListBox1.SelectedItem != null && ListBox1.SelectedIndex > 0)
{
string tempValue = ListBox1.SelectedValue;
string tempText = ListBox1.SelectedItem.Text;
int index = ListBox1.SelectedIndex;

ListBox1.SelectedItem.Value = ListBox1.Items[index - 1].Value;
ListBox1.SelectedItem.Text = ListBox1.Items[index - 1].Text;
ListBox1.Items[index - 1].Value = tempValue;
ListBox1.Items[index - 1].Text = tempText;

ListBox1.SelectedIndex--;

operateDB_move();
}
}
/**//// <summary>
/// 下移
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void LinkButton_down_Click(object sender, EventArgs e)
{
if (ListBox1.SelectedItem != null && ListBox1.SelectedIndex < ListBox1.Items.Count - 1)
{
string tempValue = ListBox1.SelectedValue;
string tempText = ListBox1.SelectedItem.Text;
int index = ListBox1.SelectedIndex;

ListBox1.SelectedItem.Value = ListBox1.Items[index + 1].Value;
ListBox1.SelectedItem.Text = ListBox1.Items[index + 1].Text;
ListBox1.Items[index + 1].Value = tempValue;
ListBox1.Items[index + 1].Text = tempText;

ListBox1.SelectedIndex++;

operateDB_move();
}
}
/**//// <summary>
/// 添加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void LinkButton_add_Click(object sender, EventArgs e)
{
if (TextBox_newCatalog.Text != "")
{
//检查同名
bool goon = true;
foreach (ListItem li in ListBox1.Items)
{
if (li.Text == TextBox_newCatalog.Text)
{
goon = false;
}
}

if (goon)
{
//操作
SqlDataSource1.InsertParameters["catalog"].DefaultValue = TextBox_newCatalog.Text;
SqlDataSource1.Insert();

//设置selected
if (ListBox1.Items.Count > 0)
{
ListBox1.SelectedIndex = 0;
}
}
else
{
Label_alert.Text = "已存在";
}
}
}
/**//// <summary>
/// 修改
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void LinkButton_edit_Click(object sender, EventArgs e)
{
if (TextBox_newCatalog.Text != "" && ListBox1.SelectedItem != null)
{
int index = ListBox1.SelectedIndex;

//检查同名
bool goon = true;
foreach (ListItem li in ListBox1.Items)
{
if (li.Text == TextBox_newCatalog.Text)
{
goon = false;
}
}

if (goon)
{
//操作
SqlDataSource1.UpdateParameters["catalog"].DefaultValue = TextBox_newCatalog.Text;
SqlDataSource1.UpdateParameters["ID"].DefaultValue = ListBox1.SelectedItem.Value;
SqlDataSource1.Update();

//设置selected
ListBox1.SelectedIndex = index;
}
else
{
Label_alert.Text = "已存在";
}
}
}
/**//// <summary>
/// 删除
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void LinkButton_del_Click(object sender, EventArgs e)
{
if (ListBox1.SelectedItem != null)
{
int index = ListBox1.SelectedIndex;
int count = ListBox1.Items.Count;

//检查该 Catalog 下是否有 Link
bool goon = true;
goon = !checkSubLink(ListBox1.SelectedValue); //下有 Link 则返回真,注意前面有个"!",有则不继续

if (goon)
{
//操作
SqlDataSource1.DeleteParameters["ID"].DefaultValue = ListBox1.SelectedItem.Value;
SqlDataSource1.Delete();

//设置selected
if (index < count - 1) //删的不是最末项
{
ListBox1.SelectedIndex = index;
}
if (index == count - 1 && index != 0) //删的是最末项,并且不是最首项
{
ListBox1.SelectedIndex = index - 1;
}
if (index == count - 1 && index == 0) //删的是最末项,并且是最首项
{
//不设索引
}
}
else
{
Label_alert.Text = "该节点下面存在Link(s),请删除后再删除该节点!";
}
}
}
xoyozo 17 年前
3,758