博客 (148)

Apple’s newest devices feature the Retina Display, a screen that packs double as many pixels into the same space as older devices. For designers this immediately brings up the question, “What can I do to make my content look outstanding on these new iPads and iPhones?”. First there are a few tough questions to consider, but then this guide will help you get started making your websites and web apps look amazingly sharp with Retina images!

retina image comparison

Things to Consider When Adding Retina Images

The main issue with adding retina images is that the images are double as large and will take up extra bandwidth (this won’t be an issue for actual iOS apps, but this guide is covering web sites & web apps only). If your site is mostly used on-the-go over a 3G network it may not be wise to make all your graphics high-definition, but maybe choose only a select few important images. If you’re creating something that will be used more often on a WI-FI connection or have an application that is deserving of the extra wait for hi-res graphics these steps below will help you target only hi-res capable devices.

Simple Retina Images

The basic concept of a Retina image is that your taking a larger image, with double the amount of pixels that your image will be displayed at (e.g 200 x 200 pixels), and setting the image to fill half of that space (100 x 100 pixels). This can be done manually by setting the height and width in HTML to half the size of your image file.

<img src="my200x200image.jpg" width="100" height="100">

If you’d like to do something more advanced keep reading below for how you can apply this technique using scripting.

Creating Retina Icons for Your Website

When users add your website or web app to their homescreen it will be represented by an icon. These sizes for regular and Retina icons (from Apple) are as follows:
ios icon samples

iPhone 57 x 57
Retina iPhone 114 x 114
iPad 72 x 72
Retina iPad 144 x 144

For each of these images you create you can link them in the head of your document like this (if you want the device to add the round corners remove -precomposed):

<link href="touch-icon-iphone.png" rel="apple-touch-icon-precomposed" />
<link href="touch-icon-ipad.png" rel="apple-touch-icon-precomposed" sizes="72x72" />
<link href="touch-icon-iphone4.png" rel="apple-touch-icon-precomposed" sizes="114x114" />
<link href="touch-icon-ipad3.png" rel="apple-touch-icon-precomposed" sizes="144x144" />

If the correct size isn’t specified the device will use the smallest icon that is larger than the recommended size (i.e. if you left out the 114px the iPhone 4 would use the 144px icon).

Retina Background Images

Background images that are specified in your CSS can be swapped out using media queries. You’ll first want to generate two versions of each image. For example ‘bgPattern.png’ at 100px x 100px and ‘bgPattern@2x.png’ at 200px x 200px. It will be useful to have a standard naming convention such as adding @2x for these retina images. To add the new @2x image to your site simply add in the media query below (You can add any additional styles that have background images within the braces of the same media query):

.repeatingPattern {
     background: url(../images/bgPattern.png) repeat;
     background-size: 100px 100px;
}

@media only screen and (-webkit-min-device-pixel-ratio: 2) {
     .repeatingPattern {
          background: url(../images/bgPattern@2x.png) repeat;
     }
}

JavaScript for Retina Image Replacement

For your retina images that aren’t backgrounds the best option seems to be either creating graphics with CSS, using SVG, or replacing your images with JavaScript. Just like the background images, you’ll want to create a normal image and one ‘@2x’ image. Then with JavaScript you can detect if the pixel ratio of the browser is 2x, just like you did with the media query:

if (window.devicePixelRatio == 2) {

//Replace your img src with the new retina image

}

If you’re using jQuery you could quickly replace all your images like this very basic example below. It’s a good idea to add a class to identify the images with hi-res versions so you don’t replace any others by mistake. I’ve added a class=”hires” for this example. Also make sure you have the standard (non-retina) image height and width set in the HTML:

<img class="hires" alt="" src="search.png" width="100" height="100" />
<script type="text/javascript">
$(function () {

	if (window.devicePixelRatio == 2) {

          var images = $("img.hires");

          // loop through the images and make them hi-res
          for(var i = 0; i < images.length; i++) {

            // create new image name
            var imageType = images[i].src.substr(-4);
            var imageName = images[i].src.substr(0, images[i].src.length - 4);
            imageName += "@2x" + imageType;

            //rename image
            images[i].src = imageName;
          }
     }

});
</script>

Server-Side Retina Images

If you’d like to implement a server-side retina image solution, I recommend checking out Jeremy Worboys’ Retina Images (which he also posted in the comments below). His solution uses PHP code to determine which image should be served. The benefit of this solution is that it doesn’t have to replace the small image with the retina one so you’re using less bandwidth, especially if you have lots of images that you’re replacing.

Website Optimization for Retina Displays

If you’re looking for additional information on creating Retina images, I’ve recently had a short book published called Website Optimization for Retina Displays that covers a range of related topics. It contains some of what is above, but also includes samples for many different situations for adding Retina images. It explains the basics of creating Retina images, backgrounds, sprites, and borders. Then it talks about using media queries, creating graphics with CSS, embedding fonts, creating app icons, and more tips for creating Retina websites.

K
转自 Kyle Larson 14 年前
5,298

最近开发了一款 iPhone 客户端应用,提交到 App Store,被拒绝(Rejected)。然后修复问题后再次提交,仍然被拒绝,奇怪的是 Resolution Center 中的拒绝原因跟上次一模一样。


幸好我在应用中做了记录客户端信息的功能,查看后发现,IP 来自“美国Apple公司”的启动版本竟然是第一次提交的版本。于是我登录 iTunes Connect 跟苹果客服联系,对方回复他们打开的确实是有问题那个版本。


正当迷茫之时,无意中在 iTunes Connect 看到 Binary Details 这个按钮,点进去一看明白了。原来,虽然我在 Xcode 中重新上传了源文件,但是这里看到的仍然是旧版本。于是我点右上角的“Reject This Binary”按钮,重新通过 Xcode 上传源代码,过会儿再进入 Binary Details 查看,还是没有变化。苦恼中。


是不是 Xcode 中要做什么处理呢?我是新手,只知道点菜单栏上的三角形按钮是调试,具体要怎么使用 Debug / Release / Run / Test / Profile / Analyze / Archive 还真是不太明白,于是对这些功能一阵乱点,意外发现 Organizer 的 Archives 中项目的 Creation Data 变成了刚才的时间,而且下面也多了一条记录,赶紧 Distribute!


一柱香后再回头去看看 Binary Details,终于看到新版本的信息了。


Waiting For Review 中……

xoyozo 13 年前
11,867

有时候已知一个 ID 的数组,需要读取这些记录内容,SQL 可以联接多个“或”关系去读取,或使用“In”语句,在 LINQ TO SQL 中可以这样来做:

List<int> ids = new List<int> { 1, 2, 3 };
List<string> tbs = db.dbTables.Where(c => ids.Contains<int>(c.ID)).ToList();
xoyozo 17 年前
5,069

我们继续讲解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/ 学习中遇到什么问题或者疑问提问的好地方。

转自 李永京 17 年前
4,989

老总总会随时扔台他朋友的本本叫我杀个毒装个软件什么的,很多都是新机预装 Vista。接触多了终于心痒痒升级自己的 Windows。其实一直想装的,可惜我的光驱只能 CD 刻录,而且跑遍整个萧山都找不到有 Vista 光盘卖,装双系统么又花时间又占空间。幸好一凡家有台记录机,所以趁周末去刻了张盘。第二天急匆匆地跑去公司,花了两个多小时把本本上将40G的东西传到服务器上备份,然后重新分区安装。

之前是有看过远景上关于安装方面的贴子,生怕中间出问题又上不了网就麻烦了。不过还是出问题了,在复制完文件后自动重启,就出现下面的错误:

 

Windows failed to start. A recent hardware or software change might be the cause.

...

If you do not have this disc, contact your system administrator or computer maufacturer for assistance

File: \windows\system32\drivers\tcpip.sys

status: 0x0000221

Info: Windows failed to load because a critical system driver is missing, or corrupt.

 

我没动过任何硬件,出现这样的错误很是摸不着头脑,想到可能的原因有:刻盘时出了问题;需要 SATA 硬盘驱动;内存不兼容……没办法,还是先找台电脑上网查查吧。身边的服务器没无线网卡不能上网,尝试在服务器安装 Nokia PC 套件还不兼容 Windows server 2003,不支持蓝牙连接。还是去其它办公室借电脑上好了。哎,不出我所料,又被逮到帮他们杀毒!汗。在网上找了半天没搜出个结果来,看来用 Vista 的人还不多,出现我的问题的人更少,我只搜到 error info 跟我相同,但 file 不同的贴子,还是没有回答的。

回来,装了两遍还是出现同样的错误,火了,先装个 XP,在 XP 下试试。漫长的等待是用电脑报打发的。。。

OK,XP 装在 D 盘,想检查是不是 SATA 硬盘的缘故,想装了 XP 应该已经有驱动了,就重起通过光盘安装 Vista 到 C 盘,啊哦,老错误。(高手别笑我,这步我都觉得荒谬)

晕,忘了 boot.ini 是在 C 盘的,进不了 XP 了,又再装了遍 XP 到 D 盘。怕了怕了,还是用镜像文件装吧。也不去研究什么原因导致的了,哎不是我的风格,可是时间宝贵呐。

老老实实装完 XP 又用虚拟光驱装入镜像,再次安装 Vista,哎,终于让我揭开她的面纱了!

一天就这么过去了,第二天继续。

Vista 已经基本解决驱动问题了,很省事,不过我还是去 HP 英文官网下了专用的驱动程序。

嗯,开始安装程序。其实 Vista 的 UAC 确实挺烦人的,特别是安装程序的时候,不过我是习惯了“用管理员身份运行”,可突然的黑屏一闪还是会让习惯的人慌一下。

在安装 .msi 程序的时候有时候会提示安装不正常,您的权限需要提升之类的错误,但无法在右键菜单找到“用管理员身份运行”项,我是这么解决的:建一个后缀名为 .cmd 的文件,写入内容:“msiexec /i C:\msi文件的地址”。然后“用管理员身份运行”这个 .cmd 文件就行了。

装完常用软件开始安装 VS 这个大家伙了。

给 C 盘分的 20 个 G 已经用了 12 个了,之前用的是 VS2005,还没装过 VS2008,所以不知道要占多少空间。前几天看过一篇文章是关于在 Vista 下安装 VS 和 SQL Server 的,作者提到的先装 VS 后装 SSMS 出错误的情况,前车之鉴,我先装了 SSMS。

最头痛的要算 IIS7 了。装入 Vista 镜像,控制面板-程序-打开或关闭 Windows 功能,参照一篇文章勾选了相关的安装项,见文。虽然我不需要在 VS2005 下调试程序,但是我暂时不想把程序框架从 2.0 升到 3.5,这几天全国范围寻找 .net 3.5 的空间商未果,真想自己弄台服务器卖空间,早起的鸟应该会有虫吃。我觉得空间商是怕技术这关,毕竟新技术万一出问题很有可能一下子解决不了,作为一个运营商就有可能被要求赔偿损失或吃官司之类的。扯远了。。。

装完 IIS7,试着架设我的 2.0 网站,经典应用程序池,身份验证,一切配置完毕,结果运行时还是出现了“IIS Worker Process 已停止工作”的对话框,偶尔出现,而且出现几次后,应用程序池就自动关闭了,用纯 HTML 站测试也一样,又把 IIS 卸了装,还是一样。试了两天没结果,希望各位达人指点!

这几天用 Vista 眼睛受不了,漂亮的外表还是很伤人的,就跟玫瑰有刺同一个道理。Areo,雅黑,梦幻桌面,让我的眼睛云里雾里的,害我拼命滴眼药水。

不过总的来说,I love vista! 推荐配置不错的朋友可以考虑升级。

xoyozo 18 年前
7,475

根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成

排列顺序从左至右依次为:六位数字地址码八位数字出生日期码三位数字顺序码一位数字校验码。 


地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。

生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。

顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。

校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。下面举例说明该计算方法。

15位的身份证编码首先把出生年扩展为4位,简单的就是增加一个19,但是这对于1900年出生的人不使用(这样的寿星不多了)

某男性公民身份号码本体码为34052419800101001,首先按照公式⑴计算:

∑(ai×Wi)(mod 11)……………………………………(1)

公式(1)中:
i----表示号码字符从由至左包括校验码在内的位置序号;
ai----表示第i位置上的号码字符值;
Wi----示第i位置上的加权因子,其数值依据公式Wi=2(n-1)(mod 11)计算得出。

i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1

ai 3 4 0 5 2 4 1 9 8 0 0 1 0 1 0 0 1 a1

Wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1

ai×Wi 21 36 0 25 16 16 2 9 48 0 0 9 0 5 0 0 2 a1

根据公式(1)进行计算:

∑(ai×Wi) =(21+36+0+25+16+16+2+9+48++0+0+9+0+5+0+0+2) = 189

189 ÷ 11 = 17 + 2/11

∑(ai×Wi)(mod 11) = 2

然后根据计算的结果,从下面的表中查出相应的校验码,其中X表示计算结果为10

∑(ai×WI)(mod 11) 0 1 2 3 4 5 6 7 8 9 10
校验码字符值ai 1 0 X 9 8 7 6 5 4 3 2
根据上表,查出计算结果为2的校验码为所以该人员的公民身份号码应该为 34052419800101001X。

C#代码:

private string per15To18(string perIDSrc)
{
    int iS = 0;

    //加权因子常数 
    int[] iW = new int[] { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
    //校验码常数 
    string LastCode = "10X98765432";
    //新身份证号 
    string perIDNew;

    perIDNew = perIDSrc.Substring(0, 6);
    //填在第6位及第7位上填上‘1’,‘9’两个数字 
    perIDNew += "19";

    perIDNew += perIDSrc.Substring(6, 9);

    //进行加权求和 
    for (int i = 0; i < 17; i++)
    {
        iS += int.Parse(perIDNew.Substring(i, 1)) * iW[i];
    }

    //取模运算,得到模值 
    int iY = iS % 11;
    //从LastCode中取得以模为索引号的值,加到身份证的最后一位,即为新身份证号。 
    perIDNew += LastCode.Substring(iY, 1);

    return perIDNew;
}


xoyozo 18 年前
9,463

许多情况下,asp.net 在 Page_Load 事件中需要动态生成控件,这对于一些新手,包括我在内,会因为回传控件消失,或重复叠加控件等原因搞得头大,经过我翻阅资料和自己的实践,以博客评论页为例,把整个框架写在下面,仅供参考。

<asp:Panel>
<asp:Panel 记录索引 3 >
<asp:Label 昵称 /> <asp:Label 时间 /> <asp:LinkButton 支持按钮_3 /> <asp:LinkButton 删除按钮_3 /> 1楼
</asp:Panel>
<asp:Panel 记录索引 5 >
<asp:Label 昵称 /> <asp:Label 时间 /> <asp:LinkButton 支持按钮_5 /> <asp:LinkButton 删除按钮_5 /> 2楼
</asp:Panel>
</asp:Panel>


记录索引是指数据库中的自动编号。

支持按钮触发事件 LinkButton_support_Click(object sender, EventArgs e)

删除按钮触发事件 LinkButton_del_Click(object sender, EventArgs e)

所有子 Panel 和内部的所有控件都是在 Page_Load 事件中动态创建的,并且不能被嵌套在 if(!IsPostBack)

“点支持累计点击数”和“点删除删除一条记录”都是需要操作数据库的,我以前的做法是操作完数据库后 .Clear() 掉所有控件,再重新生成一次,这样既浪费服务器资源,又容易出现界面上的混乱,譬如显示了两遍该文章的评论。

其实上面代码中 Panel 套 Panel 的好处就是可以根据索引直接删除相应控件,然后直接在页面呈现,而省去上述烦恼。至于累计支持数就更简单了,下面的代码可以轻松解决问题:

string n = ((Label)Panel_commentLists.FindControl("Label_against_" + id)).Text;
n
= (Convert.ToInt32(n) + 1).ToString();
((Label)Panel_commentLists.FindControl(
"Label_against_" + id)).Text = n;

如果有修改和添加评论操作,同样道理,不要重复地全部 .Controls.Add 一次。为了添加时追加一个子 Panel 方便,建议在 Page_Load 的地方传参使用方法来做。

 

补充:在现在的开发中,我更喜欢用动态生成TableRow,TableCell来操作。

xoyozo 18 年前
5,738