2015年7月15日星期三
最好的"关于什么是回调函数"问题的解答
2015年5月12日星期二
2015年5月11日星期一
使用Emgu CV不要忘记加入OpenCV Libs
有时候在VS2012中运行编译后的程序有可能会出现上图所示这个问题,可能的原因 1. 没有OpenCV Libs,如果编译成x86,我们就需要把x86的目录放入Debug和Build生成exe的文件夹里面,可以x86这个文件夹从C:\Emgu\bin里面找到。2 也有可能设置Debug和Build的路径问题,只需要确认是否正确设置就可以了。
2015年5月6日星期三
C++中的vector快速拷贝
//[1] 方法1
vector
//[2] 方法2
vector
//[3] 方法3
vector
std::copy( vec_src.begin(), vec_src.end(), vec.begin() );
// 使用的是OpenCV的方法用来测试运行的时间
double t = (double)getTickCount();
t = ((double)getTickCount() - t)/getTickFrequency();
// some codes
cout << "Times passed in milli seconds: " << t * 1000 << endl;
方法3最快,在我的笔记本上用VS2012在32bit中居然比第一种和第二种方法快近10倍,当然了也可以使用memcpy,但是其效率不会比std::copy高多少。
2014年12月23日星期二
关于CLR的runtime的一个小记录
如果我们使用引用这个通过CLR编译的dll,查看它的属性,也会发现,如下图所示的,这个dll的Runtime Version是v4.0319。
如果我们的项目使用的不是.NET framework 4.5,使用上面所述的CLR编译的项目中的namespace就会出现下面的报错:
Error 492 The type or namespace name 'XXX' could not be found (are you missing a using directive or an assembly reference?)
最简单的解决的方法就是修改我们项目的Target Framework,将其改为4.5就可以了。
2014年9月11日星期四
使用QNetworkAccessManager下载文件的一个问题
解决方法:如果加入一个QMessageBox,这样就会启动另一个event loop在这个slot里面,这样QNetworkAccessManager就会有机会完成下载文件这个工作。
链接:
http://stackoverflow.com/questions/7870017/how-can-i-download-file-from-the-internet-in-qt
2014年9月8日星期一
OpenCV放大或者缩小图像的速度
cv::resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )¶
http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html
关于它的Interpolation method(插值方法),其中:
INTER_NEAREST 最近邻插值,是最快的method并且创建blocky images并选择1个pixel去替代几个pixels,这样做得到图像的结果效果比较差。
INTER_AREA 也是一个快速计算方法,它取几个pixels的平均值,所以它比较适合缩小图像,而不是放大图像。
INTER_LINEAR 使用双线性的插值去改变图像尺寸,组成几个pixels在一起(在很多情况下是比较好的选择,但是计算速度比较慢)。
INTER_CUBIC 使用的是双三次的插值,但是计算机量比较大,所以运行速度慢,而且有时候结果看起来比较好,有时候比较差。
非常简单地,不完全正确地说,在速度上:
INTER_NEAREST > INTER_AREA > INTER_LINEAR > INTER_CUBIC
但是放大或者缩小图像后的效果上一般而言INTER_LINEAR是相对最好的。
其实,也可以使用Opencv的cv::pyrUp(使用Gaussian 金字塔分解对输入图像向上采样)和cv::pyrDown(使用 Gaussian金字塔分解对输入图像向下采样),关于使用这两个function去放大或者缩小图像,具体信息可查阅下面链接:
http://docs.opencv.org/doc/tutorials/imgproc/pyramids/pyramids.html
但是cv::pyrUp和cv::pyrDown的运算速度其实也并不高。
2014年9月7日星期日
libVLC进行memory stream延迟问题
http://stackoverflow.com/questions/19604815/main-input-error-and-delays-when-libvlc-stream-images-in-memory
为了找到错误我打开以下的参数:
"--verbose=2", // Be much more verbose then normal for debugging purpose
这样可以得到更多的debug信息。
我得到这样的信息:main warning: late buffer for mux input
经过查阅发现,正确的解决方法就是,在transcode里设置venc=x264{preset=ultrafast,tune=zerolatency}这样的参数:
sprintf(smem_options_transcode,"#transcode{venc=x264{preset=ultrafast,tune=zerolatency},acodec=none}:rtp{mux=ts,dst=127.0.0.1,port=5004}");
这样延迟可以控制在3秒以内,当然了,可以使用其他的方法进一步减少延迟,譬如在client端减少caching的数值等等。
解决方法参考:
https://forum.videolan.org/viewtopic.php?f=4&t=95364
2014年8月19日星期二
Qt Webkit 加入新的plugin路径
在Qt中使用QWebView播放flash文档(swf格式),需要加入NPSWF32.dll这个plugin,如果使用plugin要使用下面代码,去允许使用plugin:
QWebSettings *settings = QWebSettings::globalSettings();
settings->setAttribute (QWebSettings::PluginsEnabled, true);
但是如果还是无法显示flash文档,其实原因是Qt无法找到正确的plugin路径,需要使用类似以下代码,告诉Qt正确的含有NPSWF32.dll的plugin路径:
QString path = QDir::currentPath() + "/webplugins";
qputenv("QTWEBKIT_PLUGIN_PATH", path.toLocal8Bit());
2014年6月25日星期三
重新写一个精简的核心库
最近的带的项目陷入了软件开发的危机,原因是陷入自家写的库造成的泥沼越来越深。
最近几年带的大的软件项目都是使用自家写的库,工具库utils,开发库commDev,核心库core,api库,可视化库viz等等。当然了使用自家的库开发软件有时候非常有效率,但是自家开发库的升级以及维护绝对是一个大问题,维护超过5万行程序本身就是一个大问题,而且这几年来因为项目压力,常常直接将很多东西放入核心库core里,导致核心库臃肿不堪,而且关于库的使用的实例程序以及接口或者api更本做不到时常更新,有很多文档已经四五年了,更本无法使用,所以导致最最大的痛苦是教新人使用我们的库。更为恐怖的是核心库对其他外部库的依赖越来越多,从OpenCV,Boost到现在的至少10个以上的第三方库,但是核心库更本也没有根据外部库进行更新,至今核心库还在使用OpenCV2.0。更为痛苦的是自家写的库还是使用VS2008进行编译,因为实在太大,以至于没有人有勇气进行修整,并使用最新的编译器进行编译。
现在实在受不了了,我终于决定重写核心库,并且放弃工具库utils,开发库commDev,api库,可视化库viz。新的核心库只有两个依赖OpenCV和Qt这两个第三方库的巨无霸。放弃的工具库utils,开发库commDev,api库,可视化库viz,全部使用Qt代替。新的核心库就叫CoreLite,只依赖于最新的Qt5.3和OpenCV2.49,保持绝对的精简,而且可以根据Qt和OpenCV的升级进行编译,而且使用VS2012进行开发和编译,希望能做到根据OpenCV更新的频率进入版本更新。
- 新的库CoreLite的第一个tag就是CoreLite290,使用和OpenCV一样的文档结构。
\build\include
\build\x86 (\build\x86\vc11\bin, \build\x86\vc11\lib)
\sources\modules\ - 新的库使用Qt的QThread。
- 控制Class的总数,只包括Qt或OpenCV无法提供的一些特性,例如Producer-Comsumer-Data Sink结构。
- 带几个实例。
- 保证库的可读性,使用Qt的api的写作标准。
- 最大程度保证库的可维护性,其实就是要保持精简。
目前想到的就是这些了,以后在重新的过程中,如果还有什么想法,我希望能写下来记录一下,期望可以用一个星期将新的核心库改写完成。
2014年6月14日星期六
VS 2008编译的程序部署的一个问题解决
最近遇到一个问题,在一台机器上使用VS 2008编译的程序无法在其他机器上运行,马上想到了以前提到过的关于Side-by-Side问题, 但是安装了Microsoft Visual C++ 2008 SP1 Redistributable Package (x86)后程序还是无法运行,而且没有什么错误信息。然后使用Windows里的Computer Management里的Event Viewer的Windows Logs发现这个程序无法运行的原因在于其调用的一个动态链接库DLL。然后我查看了一下这个DLL的Manifest,原来多了一个Microshoft.VC90.DebugCRT的依赖,如下图所示。如果我们在机器上没有安装VS 2008当然就会没有Microshoft.VC90.DebugCRT的依赖需要的msvcm90d.dll,msvcp90d.dll,msvcr90d.dll,所以程序就无法运行了。
解决的方法就是使用在release模式下编译,或者如下图所示,修改C++ Project的Property里的Linker-->Debugging选项页,将Generate Debug Info修改成No,将Debuggable Assembly改成No Debuggable attribute emitted,原来如下图a所示,修改后如下图b所示:
现在再编译一次,查看一下新生成的DLL的Manifest可以发现Microshoft.VC90.DebugCRT的依赖已经没有了,现在程序应该可以在其他机器上运行了。
2014年1月27日星期一
Emgu CV使用1
最近开始使用Emgu CV,也就是在.NET可以使用的OpenCV,Emgu CV是一个.Net的wrapper。使用从C++转到C#中写OpenCV代码,开始时候还真的很不习惯,以下将简单整理一下最近的一些笔记。
如何将Grayimage转换到Matrix<float>,注意rows cols和height width的关系:
Image<Gray, float> img = new Image<Gray, float>("c:\\test_image.jpg");
int rows = img.Height;
int cols = img.Width;
Matrix<float> tmp_matrix= new Matrix<float>(rows, cols);
CvInvoke.cvConvert(img, tmp_matrix);
如何显示图:
//The name of the window
String win1 = "Test Window";
//Create the window using the specific name
CvInvoke.cvNamedWindow(win1);
Image<Bgr, Byte> img = new Image<Bgr, Byte>("c:\\test_image.jpg");
CvInvoke.cvShowImage(win1, img.Ptr);
//Wait for the key pressing event
CvInvoke.cvWaitKey(1);
//Destory the window
CvInvoke.cvDestroyWindow(win1);
如何画一个正方形在图上:
Rectangle box = new Rectangle(121, 57, 75, 97);
Image<Bgr, Byte> img = new Image<Bgr, Byte>("c:\\test_image.jpg");
img.Draw(box, new Bgr(Color.DarkOrange), 2);
如何计算一个积分图integral image,在C++中我们可以使用integral(frame, imageIntegral, CV_32F),在C#中可以这样做:
Image<Gray, double> cvImageIntegral = null;
cvImageIntegral = frame.Integral();
如何计算标准差,标准差就是方差的算术平方根,反映组内个体间的离散程度,标准差与期望值之比为标准离差率。
Matrix<float> mat = ... // your input matrix
MCvScalar average = new MCvScalar();
MCvScalar std = new MCvSaclar();
CvInvoke.cvAvgSdv(mat, ref average, ref std, IntPtr.Zero);
2013年11月28日星期四
转换QImage到FFmpeg的internal YUV format
今天正巧有时间,在家里修改并整理一下我3年前写的视频播放和储存代码。FFmpeg更新非常快,突然发现我还在使用2011年09月23日的FFmpeg版本。最新版本已经到了2.1.1(http://ffmpeg.zeranoe.com/builds/win32/dev/),刚刚下载了,试着编译以前写的代码,发现很多API都变了,无法编译了,懒得再进行调整了,放弃使用新版本了,新的特性暂时用不到。我将2011年09月23日的FFmpeg版本作为项目的标准lib,打包上传到服务器上,还有SVN里。
刚刚在修改“转换QImage到FFmpeg的internal YUV format的方法”,这个方法是从QtFFmpegWrapper项目抄来的,https://code.google.com/p/qtffmpegwrapper/。我发现,我刚刚写的新代码中使用的是QImage::Format_RGB888,如果直接使用这个方法转换的frame就会不正确,是黑白的而且尺寸也不对,想了一下,其实只需要将ffmpeg::sws_getCachedContext这个API里的Source PixelFormat 改成PIX_FMT_RGB24就行了,简单而言只要注意将QImage的PixelFormat和AVFrame的PixelFormat正确对应就行了,具体代码如下面所示。
void convertImage_sws(const QImage &img)
{
// Check if the image matches the size
if(img.width() != getWidth() || img.height() != getHeight())
{
printf("Wrong image size!\n");
return false;
}
if(img.format() != QImage::Format_RGB32 && img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_RGB888)
{
printf("Wrong image format\n");
return false;
}//img_convert_ctx = ffmpeg::sws_getCachedContext(img_convert_ctx, getWidth(), getHeight(),
// ffmpeg::PIX_FMT_BGRA, getWidth(),getHeight(), ffmpeg::PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);img_convert_ctx = ffmpeg::sws_getCachedContext(img_convert_ctx, getWidth(), getHeight(), ffmpeg::PIX_FMT_RGB24, getWidth(), getHeight(), ffmpeg::PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
if (img_convert_ctx == NULL)
{
printf("Cannot initialize the conversion context\n");
return false;
}uint8_t *srcplanes[3];
srcplanes[0] = (uint8_t*)img.bits();
srcplanes[1] = 0;
srcplanes[2] = 0;int srcstride[3];
srcstride[0] = img.bytesPerLine();
srcstride[1] = 0;
srcstride[2] = 0;
ffmpeg::sws_scale(img_convert_ctx, srcplanes, srcstride, 0, getHeight(), ppicture->data, ppicture->linesize);return true;
}
2013年11月26日星期二
开始使用C++/CLI编程
一直以来一直是使用C++和C#,最近接触了C++/CLI并开始使用它编写程序,已经写了两三千行程序,使用C++/CLI对一个C++和C#程序员来说简直是轻而易举,C++/CLI也会给我们带来很多好处,有了C++/CLI对于.NET平台上的C++来说就是多了一个非常好用的武器,C++在.NET平台中得到极大的补充,所谓“C++/CLI”是静态C++对象模型到CLI的动态组件对象编程模型的捆绑。简而言之就是如何用C++在·NET中编程,而不是C#或Visual Basic,它实现了ISOC++和.NET的无缝连接。像C#和CLI本身一样符合ISO标准。微软的.NET的基础CLR(Common Language Runtime,通用语言运行时)就是CLI的一个实例。
百度百科,维基百科:
http://baike.baidu.com/view/459502.htm?noadapt=1
http://zh.wikipedia.org/wiki/C%2B%2B/CLI
以下内容转载自《C++/CLI in action》
The Common Language Infrastructure (CLI) is an architecture that supports a dynamic language-independent programming model based on a Virtual Execution System.
The role of C++/CLI
C++ has been paired with language extensions before, and the result hasn’t always been pretty. Visual C++ 2005 is the first version of a Microsoft C++ compiler that has implemented the C++/CLI specification. This means three things for the C++ developer:
■ C++ can be used to write applications that run on the .NET Framework. There is no need to learn a totally new language or to abandon all the C++ knowledge and experience built up through years of coding.
■ C++/CLI lets developers reuse their native C++ code base, saving the agony of having to rewrite all the existing code to enable it to run on the .NET Framework.
■ C++/CLI is designed to be the lowest-level language for the .NET Framework. For writing purely managed applications, it’s your most powerful choice; or, as I like to say, “C++/CLI actually lets you smell the CLR (Common Language Runtime).”
C++/CLI. C++ with some additional keywords and semantics that support .NET
One of the core aspects of the CLR is a unified type system called the Common Type System (CTS). The CTS defines the model followed by the CLR for the declaration and usage of CLI types.
What is the .NET Framework?
The .NET Framework provides an abstraction layer on top of the native operating system that allows applications compiled into a special intermediate language called Microsoft Intermediate Language (MSIL) to run under a managed environment— where both execution and memory are managed by various parts of the framework. Its two primary components are the Common Language Runtime (CLR) and an extensive Base Class Library (BCL). The CLR is responsible for the execution of .NET applications, inducing memory management through its built-in Garbage Collector (see the section on memory management for more information), whereas the BCL provides various hierarchical class libraries for creating rich user interfaces (UIs), both for the desktop and for the Web—accessing data, security, web services, and many more commonly-performed programming chores.
2013年11月21日星期四
TwinCAT 3使用记录2:ADS介绍
今天简要地介绍一下ADS和一个简单的实际例程。ADS就是Automation Device Specification,通过使用Beckhoff的ADS接口可以和一些virtual Automation Device或者是Windows的程序相连。如果安装了TwinCAT3可以在C:\TwinCAT\AdsApi\TcAdsDll\Lib\找到TcAdsDll.lib,这就是我们需要的ADS的lib文件。对于ADS接口,最重要的操作就是READ和WRITE了,以下是API的说明。
long __stdcall AdsSyncWriteReq( AmsAddr* pServerAddr, // Ams address of ADS server
unsigned long indexGroup, // index group in ADS server interface
unsigned long indexOffset, // index offset in ADS server interface
unsigned long length, // count of bytes to write
void* pData // pointer to the client buffer
);__declspec( dllexport )
long __stdcall AdsSyncReadReq( AmsAddr* pAddr, // Ams address of ADS server
unsigned long indexGroup, // index group in ADS server interface
unsigned long indexOffset, // index offset in ADS server interface
unsigned long length, // count of bytes to read
void* pData // pointer to the client buffer
);
先启动TwinCAT XAE(VS 2010)也就是VS 2010,新建一个TwinCAT的Project。在SYSTEM里的License选项里可以点击“Activate 7 Days Trial License”,然后会出现以下的对话框,填入生成的Code就完成了注册,用于开发,我们可以一直“Activate 7 Days Trial License”并可以使用TwinCAT 3的完整功能。
如果我们使用了Beckhoff的EtherCAT的IO模块,并通过Ethernet线和PC相连,我们可以将这个设备和TwinCAT相连,在Solution Explorer里的I/O一栏里,展开它,点击Devices,点鼠标右键,点选Scan就可以连接我们的EtherCAT I/O模块了,如下图所示,也可使用工具栏上的Scan图标。
如果发现有正确连接,就会出现下图的对话框。
点选OK,我们就是Active Free Run了。然后在Solution Explorer会看到Device的信息,如下图所示。
如果我们点选譬如Term 2 (EL2004),并展开它,就会看到这个模块的Channel,如果点击其中一个Channel就会看到上面的I/O,点击这个I/O就会在Variable这个Tab里找到ADS info,如下图所示。
接下来我们就要使用这个ADS Info,并使用上面提到的API对其进行读和写。我们可以在以下链接中找到SAMPLE2(写)和SAMPLE3(读),这两个例程使用了SOFT PLC,提供的PLC可以加载到TwinCAT Project里,这里我们不使用PLC而是直接使用我们上面已经连接好的I/O模块:
http://download.beckhoff.com/download/Software/TwinCAT/TwinCAT3/Samples/TC1000-ADS/ADS/C/
#include <iostream>
#include <windows.h>
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h"using namespace std;
void main()
{
long nErr, nPort;
AmsAddr Addr;
PAmsAddr pAddr = &Addr;
DWORD dwData;// Open communication port on the ADS router
nPort = AdsPortOpen();
nErr = AdsGetLocalAddress(pAddr);
if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';
pAddr->port = 11;// Read the vlaue of the user, who has to be written to the PLC
cout << "Value: ";
cin >> dwData;//Port: 11, IGrp: 0x3040010, IOffs: 0xC10000D1, Len: 1
nErr = AdsSyncWriteReq( pAddr, 0x3040010, 0xC10000D1, 0x1, &dwData );
if (nErr) cerr << "Error: AdsSyncWriteReq: " << nErr << '\n';// Close the communication port
nErr = AdsPortClose();
if (nErr) cerr << "Error: AdsPortClose: " << nErr << '\n';
}
例程中的代码只需进行两处的改动(红笔处),就可以将我们输入的Data通过ADS接口传递给我们的EtherCAT I/O模块,这里使用的port of ADS server,index group in ADS server interface,index offset in ADS server interface,count of bytes to write,就是我们在上图看到的我们读到的ADS info。对于Read的例程SAMPLE3我就不多加描述了,就是使用AdsSyncReadReq这个API,然后给其相对应的ADS info就行。
2013年11月1日星期五
ASP.NET MVC 4使用技巧9:使用Google Charts和JSON
Google Charts 令人爱不释手,功能强大而且简单美观,文档非常完善。
https://developers.google.com/chart/
这里同时推荐一下Playerground,真是是一个非常好用的“工具”,可以非常方便地进行测试。
http://code.google.com/apis/ajax/playground/
如果想画一个line chart,并使用JSON得到做图的数据,很简单,以下就是一个简单的例子,在我们的.cshtml中添加上我们需要的js代码,在这个例子中,
- 引用jsapi库并使用一系列Google Chart API,进行做图。
- 通过点击一个button激活做图function。
- 通过google.visualization.events.addListener得到点击line的事件。
- 通过$.post('/YourController/GetDrawJsonData', {}, function (d) { … …); }); 从我们的Controller中得到Json数据。
<script type="text/javascript" src="//www.google.com/jsapi"></script>
<script type="text/javascript">google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
var button_show_all = document.getElementById('show_all');
//-- Set a button onclick event // Multi graph. button_show_all.onclick = function () { var options = { title: 'All Heuristic Methods', colors: ['#E6E6E6'], //colors: ['#93ACE7'], legend: { position: 'none' } //legend: { position: 'top', maxLines: '5' } //series: [{ color: 'blue', visibleInLegend: true }, { color: 'blue', visibleInLegend: true }]};
// Add our selection handler. google.visualization.events.addListener(chart, 'select', lineChartHandler); //-- Chart click event function lineChartHandler() { var selection = chart.getSelection(); if (selection.length > 0) { alert('A Line was selected');}
}
$.post('/Plan/GetDrawJsonData', {}, function (d) { //alert(d); var data = google.visualization.arrayToDataTable(d); // At the end draw the chart.chart.draw(data, options);
});
}
}
</script>
它的html代码就更简单了:
<input id="show_all" type="button" class="btn btn-info" value="Show All Charts" />
<br />
<div id="chart_div" style="width: auto; height: 400px;">
</div>
在Controller中只需要加入生成JSON数据的方法:
public ActionResult GetDrawJsonData(){ List<object> data_todraw = ... ... ...; return Json(data_todraw);}
进阶一下,如果想要通过JSON改变做图的options,譬如说是颜色,其实也很方便,先在js中加入一个chart_opt的arrary:
var chart_opt = new Object();
chart_opt.title = "Heuristic Method";var colors = new Array();
colors[0] = "#93ACE7"chart_opt.colors = colors;
var lengend = new Object();
lengend.position = 'none';chart_opt.legend = lengend;
然后通过一个function得到json数据,这里的row: input_counter是一个输入,我们的Controller的方法可以通过这样的方式得到这个输入:
$.post('/YourController/GetDrawJsonOptionSingle', { row: input_counter },function (f) { //console.log(f); //If for some reason you cannot modify your server side script to provide //a valid JSON in the tags property you could still use eval instead of $.parseJSON:var tags = $.parseJSON(response.tags); var colors_tmp = eval(f);console.log(colors_tmp);
for (i = 0; i < colors_tmp.colors.length; i++) {colors[i] = colors_tmp.colors[i];
}
});
与之对应的Controller里的method,需要使用一个Class里面定义colors的List,最后通过return Json(…)返回JSON数据:
public class ChartOptions
{public List<string> colors;
}
public ActionResult GetDrawJsonOptionSingle(int row)
{
ChartOptions tmp = new ChartOptions();tmp.colors = new List<string>();
for (int i = 0; i < ROW_COUNT_ALL; i++)
{ if (i == row) { tmp.colors.Add("#F30A0A");}
else { tmp.colors.Add("#E6E6E6");}
}
return Json(tmp);}
2013年8月13日星期二
ASP.NET MVC 4使用技巧8:自定义CheckBox及ActionResult的Subtypes
今天简单介绍一下如何编写一个自定义的CheckBox:
<script type="text/javascript">
function unhide(id_name, check_box) {
var check = (check_box.checked) ? "block" : "none";
document.getElementById(id_name).style.display = check;
}
</script>
@Html.CheckBoxFor(model => model.NotifyEmail, new { @checked = "unchecked" , @onclick="unhide('hidden-input-email', this)"})Email Notification<br>
<div id="hidden-input-email" style="display:none">
<p>
@Html.LabelFor(model => model.Email)
@Html.TextBoxFor(model => model.Email, new { @readonly="readonly" })
</p>
<div class="editor-field">
@Html.TextAreaFor(model => model.EmailInfos, new { style = "width: 200px; height: 100px;" })
</div>
上面的View代码,使用了自定义的CheckBox
简单的说明一下:
- @Html.CheckBoxFor(model => model.NotifyEmail, new { @checked = "unchecked" , @onclick="unhide('hidden-input-email', this)"})Email Notification<br>
- 当我们点击这个CheckBox的时候会将隐藏的输入框显示出来,这里使用了一个简单的Javascript,当@onclick的事件被触发时。
- 同时这里使用@checked = "unchecked"设置初始为unchecked。
- 参数:model => model.NotifyEmail是我们对于checkbox的view model binding。
- 我们的TextAreaFor也通过参数:new { style = "width: 200px; height: 100px;" }自定义了大小。
ActionResult有很多种Subtypes,我今天才知道,以前只用过3种。
出处:http://forums.asp.net/t/1448398.aspx
ViewResult - Renders a specifed view to the response streamPartialViewResult - Renders a specifed partial view to the response stream
EmptyResult - An empty response is returned
RedirectResult - Performs an HTTP redirection to a specifed URL
RedirectToRouteResult - Performs an HTTP redirection to a URL that is determined by the routing engine, based on given route data
JsonResult - Serializes a given ViewData object to JSON format
JavaScriptResult - Returns a piece of JavaScript code that can be executed on the client
ContentResult - Writes content to the response stream without requiring a view
FileContentResult - Returns a file to the client
FileStreamResult - Returns a file to the client, which is provided by a Stream
FilePathResult - Returns a file to the client






