PDA

View Full Version : آموزش: ساخت و توسعه یک ادیتور متن مبتی بر ASP.NET



clover
دوشنبه 07 فروردین 1391, 15:12 عصر
با سلام
از اونجایی که ادیتور های متن مبتنی بر وب ابزار های پر کاربردی هستند و همچین از اونجایی که در این تالار به دفعات در این مورد سوال و درخواست شده، تصمیم گرفتم شروع به پیاده سازی و توسعه ی یک ادیتور ساده و سبک برای ASP.NET کنم.
ممکنه براتون سوال پیش بیاد که با وجود این همه ادیتور موجود چه نیازی به این کار هست؟
پاسخ من این هست که اکثر ادیتور های موجود از مشکلات زیادی از جمله حجم زیاد، پیچیدگی آماده سازی و استفاده در ASP.NET و ... رنج می برند که اکثرا دردسر ساز هست. همچنین سوال دیگه ای که ممکنه پیش میاد این هست که چرا مبتنی بر ASP.NET و نه جاوا اسکریپت؟
این هم جواب ساده ای داره و اون اینه که من یک برنامه نویس NET. هستم و با این محیط احساس راحتی می کنم، مطمئنا اگر از ادیتوری مبتنی بر دات نت استفاده کنم توان سفارشی سازی و توسعه ی اون رو خواهم داشت، از طرف دیگه پیاده سازی چنین ابزاری با استفاده از استانداردهای زبان #C جذابیت خاص خودش رو خواهد داشت.


87892

- قابلیت قالب بندی جعبه ابزار
- رفع باگ و بروز رسانی کدهای جاوا اسکریپت

کنترل مورد نظر رو به همراه آخرین تغییرات از لینک زیر می تونید دانلود کنید:
http://barnamenevis.org/showthread.php?333818-%D8%B3%D8%A7%D8%AE%D8%AA-%D9%88-%D8%AA%D9%88%D8%B3%D8%B9%D9%87-%DB%8C%DA%A9-%D8%A7%D8%AF%DB%8C%D8%AA%D9%88%D8%B1-%D9%85%D8%AA%D9%86-%D9%85%D8%A8%D8%AA%DB%8C-%D8%A8%D8%B1-ASP.NET&p=1519856&viewfull=1#post1519856

clover
دوشنبه 07 فروردین 1391, 15:14 عصر
در این مقاله، در طی ساختن یک کنترل ویرایشگر متن مبتنی بر وب (Online Rich Text Editor)، با نحوه ایجاد و توسعه ی یک کنترل در ASP.NET نیز آشنا خواهید شد.

مقدمه
ASP.NET به همراه مجموعه ای کامل و قوی از کنترل ها عرضه شده است، پس چرا ما باید کنترل های خودمان را بسازیم؟


By creating our own controls, we can then build powerful, reusable visual components for our Web application’s user interface.
این مقاله قصد دارد روند توسعه ی یک کنترل ASP.NET را برای شما شرح دهد. همچنین خواهید دید که ایجاد کنترل های سفارشی چگونه باعث بهبود کیفیت نرم افزار های شما و همچنین رابط کاربری آنها خواهد شد.
کنترل های سفارشی ASP.NET (ASP.NET Custom Controls) انعطاف بیشتری نسبت به کنترل های کاربر (User Controls) دارند. ما می توانیم کنترل های سفارشی ایجاد کنیم که از کنترل های سمت سرور دیگری مشتق شده باشند و سپس به توسعه ی آنها بپردازیم. همچنین می توانیم این کنترل ها را دربین پروژه های مختلف به صورت مشترک مورد استفاده قرار دهیم. به طور معمول این کنترل ها در یک کتابخانه ی مجزا از نرم افزار تحت وب ما ایجاد شده و به صورت جداگانه کامپایل می شوند. در نتیجه با اضافه کردن این کتابخانه به پروژه های خود قادر خواهیم بود تا از کنترل مورد نظر، در این پروژه ها استفاده کنیم.

بررسی اجمالی ویرایشگر های متنی مبتنی بر وب
اگرچه امروزه همه ی مرورگرها می توانند Rich Text (متون دارای استایل) را نمایش دهند، اما هنوز هم ورود داده ها توسط کاربر، محدود به جعبه متن هایی هستند که فقط از متن ساده (یک نوع فونت و یک استایل) پشتیبانی می کنند. اینترنت اکسپلورر اولین مرورگری بود که قابلیت ویرایش بخش هایی از متن را با استفاده از ویژگی به نام “designMode” معرفی کرد. پس از آن موزیلا نیز این قابلیت را در ورژن 1.3 مرورگر خود پیاده کرد و امروزه اکثر مرورگرهای معروف دنیا چنین قابلیتی را در اختیار کاربرانشان قرار می دهند.
با اینکه قابلیت ویرایش متن به عنوان یک استاندارد جزو ویژگی های HTML4 نیست اما شاهد این هستیم که به صورت فراگیر در سرویس هایی نظیر جیمیل و وردپرس مورد استفاده قرار گرفته است. از این رو در HTML5 با معرفی ویژگی “contentEditable” تلاش شده است تا این قابلیت به صورت استاندارد پیاده سازی شود.
در این مقاله ما برای طراحی ویرایشگر متنی مبتنی بر وب خود از همان ویژگی designMode استفاده خواهیم کرد که قابلیت ویرایش متن درون اسناد HTML را به ما خواهد داد.
قابلیت ویرایش متن با تنظیم مقدار ویژگی designMode یک سند HTML (به طور مثال سندی در داخل یک iframe) به “on” برای آن سند فعال خواهد شد. در این حالت محتویات سند مورد نظر قابلیت ویرایش و اعمال استایل مورد نظر از طرف کاربر را خواهد داشت.
برای نمونه این بلوک کد را به انتهای یک صفحه ی HTML اضافه و صفحه را در مرورگر خود اجرا کرده و نتیجه ی تغییرات را مشاهده کنید (اجزای صفحه قابلیت ویرایش پیدا خواهند کرد):

<script type="text/javascript">
document.designMode = 'on';
</script>
برای اطلاعات بیشتر در این زمینه می توانید به منابع زیر مراجعه کنید:

http://msdn.microsoft.com/en-us/library/ms533720(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms537837(VS.85).aspx
http://www.quirksmode.org/dom/execCommand.html

همچنین در زمانی که قابلیت ویرایش متن را برای یک سند فعال کنید با استفاده از متد execCommand قادر خواهید بود افکت های مورد نظر خود (تغییر رنگ، فونت و ...) را بر رو محتوای آن اعمال کنید. همچنین برای کسب اطلاعات بیشتر در مورد این تابع و پارامتر های آن می توانید به منابع زیر مراجعه کنید:

http://msdn.microsoft.com/en-us/library/ms536419(v=VS.85).aspx
http://devedge-temp.mozilla.org/viewsource/2003/midas/01/index_en.html
http://www.quirksmode.org/dom/execCommand.html


برای درک چگونگی کارکرد موارد توضیح داده شده در بالا به مثال زیر توجه کنید:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>

</head>
<body>
<iframe id="oIFrame"></iframe>
<br />
<input type="button" value="Bold" onclick="setToBold()" />

<script type="text/javascript">
var oIFrame = document.getElementById("oIFrame");
setTimeout("oIFrame.contentWindow.document.designMode = 'on';", 10);

function setToBold() {
oIFrame.contentWindow.document.execCommand('bold', false, null);
}
</script>
</body>
</html>


نقطه ی صفر: شروع
تمام چیزی که برای شروع به آن نیاز دارید یک نسخه از Visual Studio Express یا Visual Web Developer Express است. همچنین در صورتی که شما یک نسخه ی کامل از Visual Studio را ندارید می توانید نسخه ی رایگان آنرا از اینجا (http://www.asp.net/downloads) دانلود کنید.
ویرایشگر متنی که ما قصد ایجاد آنرا داریم در سمت مشتری از همان چند خط کد جاوا اسکریپت که در بالا به صورت نمونه آورده شد به همراه مقداری کد HTML و CSS برای طراحی ظاهری بهره می برد و و سایر ویژگی های آن (از جمله امکان تغییر ویژگی های ظاهری و کاربردی، امکان نصب افزونه ها و استفاده از قالب های مختلف و...) به کمک امکانات ASP.NET پیاده خواهد شد.


مرحله ی اول: ایجاد یک پروژه ی کنترل سفارشی
در ابتدا ما به یک پروژه ی کتابخانه ی کلاس احتیاج داریم تا کنترل سفارشی ما را نگهداری کند. با ایجاد کنترل سفارشی مورد نظر در یک کتابخانه ی کلاس مجزا، ما قادر خواهیم بود تا پروژه ی مورد نظر را به صورت یک فایل DLL کامپایل کرده و در هر پروژه ای که به آن نیاز داشتیم از آن استفاده کنیم.
پروژه ی ASP.NET مورد نظر خود را در ویژوال استدیو باز (یا ایجاد) کنید. در قسمت Solution Explorer بر روی نام راه حل خود کلیک راست کرده و گزینه ی Add > New Project را از منوی باز شده انتخاب کنید.
در پنجره ی باز شده (Add New Project) . مطابق شکل زیر نوع پروژه (Project type) را Web انتخاب کرده و قالب پروژه (Template) را نیز ASP.NET Server Control انتخاب کنید:


84706

در قسمت نام، CustomControls را وارد کرده و کلید OK را فشار دهید. یک پروژه ی جدید کنترل سفارشی ایجاد شده و همراه با آن ویژوال استدیو یک کنترل نمونه نیز ایجاد می کند که می توانید آن را حذف کنید زیرا نیازی به آن نخواهیم داشت.


مرحله دوم: اضافه کردن یک کنترل سفارشی به پروژه
در قسمت Solution Explorer بر روی پروژه ی CustomControls راست کلیک کرده و گزینه ی Add > New Item را از منوی باز شده انتخاب کنید.
در پنجره ی باز شده (Add New Item) . مطابق شکل زیر شاخه ی Web را انتخاب کرده و قالب را نیز ASP.NET Server Control انتخاب کنید.


84708

در قسمت نام، RichTextEditor را وارد کرده و کلید Add را فشار دهید. یک کنترل سفارشی جدید ایجاد شده و به پروژه ی شما اضافه خواهد شد.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CustomControls
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:RichTextEditor runat=server></{0}:RichTextEditor>")]
public class RichTextEditor : WebControl
{
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string Text
{
get
{
String s = (String)ViewState["Text"];
return ((s == null) ? String.Empty : s);
}

set
{
ViewState["Text"] = value;
}
}

protected override void RenderContents(HtmlTextWriter output)
{
output.Write(Text);
}
}
}
کدی که در بالا مشاهده می کنید کدی است که توسط ویژوال استدیو برای یک کنترل سفارشی ایجاد شده است. برای شروع کار ما نیاز داریم تا تغییراتی را در این کد ایجاد نماییم. اولین کاری که باید انجام دهیم این است که مطابق شکل زیر کلیه ی کد های موجود در کلاس ایجاد شده را حذف کنیم:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CustomControls
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:RichTextEditor runat=server></{0}:RichTextEditor>")]
public class RichTextEditor : WebControl
{

}
}

همانطور که در بالا مشاهده می کنید کلاس RichTextEditor از کلاس System.Web.UI.WebControl مشتق شده است. در حقیقت کلیه کنترل های سمت سرور ASP.NET از این کلاس مشتق شده اند.

مرحله سوم: به روز رسانی اعلان کلاس
در قسمت اعلان کلاس به صورت پیشفرض یک ویژگی با نام Text به عنوان ویژگی پیشفرض کلاس RichTextEditorمشخص شده است و از آنجایی که کلاس مورد نظر ما دارای چنین ویژگی نیست این بخش را نیز حذف می کنیم.
همچنین برای اینکه بتوانیم بدون نیاز به کلاس Page و دسترسی به شی Request آن به داده هایی که طی پست بک به سرور ارسال می شوند دسترسی داشته باشیم، بهترین راه استفاده از رابط IPostBackDataHandler می باشد. بنابر این کلاس ما علاوه بر کلاس WebControl باید از رابط نیز ارث ببرد. متد LoadPostData متد مورد نظر ما برای دستیابی به داده های ارسال شده به سرور است. پس از اعمال تغییرات کدهای ما باید به شکل زیر باشند:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CustomControls
{
[ToolboxData("<{0}:RichTextEditor runat=server></{0}:RichTextEditor>")]
public class RichTextEditor : WebControl, IPostBackDataHandler
{

}
}


مرحله چهارم: افزودن ویژگی ها (Properties)
کلاس RichTextEditor ما فقط یک ویژگی از نوع متنی و با نام InnerHTML خواهد داشت که از آن برای دسترسی به محتویات ادیتور استفاده خواهیم کرد. از آنجایی که این محتویات باید پایدار بوده و طی پست بک صفحه بازیابی شوند، به جای استفاده از یک متغیر از اعضای داده ای کلاس، از ViewState به عنوان محل ذخیره سازی این محتوا استفاده خواهیم کرد.
خطوط زیر را به کلاس RichTextEditor اضافه کنید:

public string InnerHTML
{
get
{
string text = ViewState["InnerHTML"] as string;
return string.IsNullOrEmpty(text) ? string.Empty : text;
}

set
{
ViewState["InnerHTML"] = value;
}
}
پس از اعمال تغییرات کدهای ما باید به شکل زیر باشند:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CustomControls
{
[ToolboxData("<{0}:RichTextEditor runat=server></{0}:RichTextEditor>")]
public class RichTextEditor : WebControl, IPostBackDataHandler
{
public string InnerHTML
{
get
{
string text = ViewState["InnerHTML"] as string;
return string.IsNullOrEmpty(text) ? string.Empty : text;
}

set
{
ViewState["InnerHTML"] = value;
}
}

}
}


مرحله پنجم: بازیابی داده های ارسالی به سرور
در صورتی که پست بک اتفاق بیفتد محتوای کنترل ادیتور باید توسط داده های ارسالی به سرور به روز رسانی شود. همانطور که قبلا گفته شد برای این منظور می توانیم با پیاده سازی متد LoadPostData به داده های ارسالی دسترسی داشته باشیم، بدین شکل که در هر بار پست بک وب فرم به سرور، فریمورک داده های مرتبط با هر کنترل را با توجه به id المنت های موجود در فرم و UniqueID کنترل های سمت سرور با یکدیگر تطبیق داده و متد LoadPostData مربوط به کنترل های مورد نظر را به همراه داده های ارسالی در پارامتر های این متد فراخوانی می کند.
خطوط زیر را به کلاس RichTextEditor اضافه کنید:

public bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
string postedValue = postCollection[postDataKey];
InnerHTML = postedValue;
return false;
}

public virtual void RaisePostDataChangedEvent()
{

}
پس از اعمال تغییرات کدهای ما باید به شکل زیر باشند:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Specialized;

namespace CustomControls
{
[ToolboxData("<{0}:RichTextEditor runat=server></{0}:RichTextEditor>")]
public class RichTextEditor : WebControl, IPostBackDataHandler
{
public string InnerHTML
{
get
{
string text = ViewState["InnerHTML"] as string;
return string.IsNullOrEmpty(text) ? string.Empty : text;
}

set
{
ViewState["InnerHTML"] = value;
}
}
public bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
string postedValue = postCollection[postDataKey];
InnerHTML = postedValue;
return false;
}
}
}

مرحله ی ششم: بازنویسی متد OnPreRender
کنترل مورد نظر ما در مرورگر مشتری ممکن است برای انجام برخی عملیات نیاز به مقداری کد جاوا اسکریپت در صفحه ی HTML داشته باشد. جایی که می توانیم این کد ها را به صفحه اضافه کنیم متد بازنویسی شده ی OnPreRender می باشد. متد بازنویسی شده ی OnPreRender زیر را به کلاس RichTextEditor اضافه کنید:

protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);

}

مرحله هفتم: افزودن جاوا اسکریپ
متنی که قصد ویرایش آن را داریم در یک iframe قرار خواهد گرفت تا از دیگر المنت ها و استایل های صفحه مجزا باشد. برای فعال کردن حالت designMode سند داخل iframe از یک تابع جاوا اسکریپت کمک خواهیم گرفت، همینطور برای اعمال افکت های مورد نظر خود از قبیل Bold، Italic و Underline از توابعی جاوا اسکریپت که در زیر خواهید دید استفاده می کنیم:

function turnOnDesignMode(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.designMode = "on";
}
function setToBold(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.execCommand('bold', false, null);
}
function setToItalic(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.execCommand('italic ', false, null);
}
function setToUndeline(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.execCommand('underl ine', false, null);
}
ابتدا سه ثابت با نام های CLIETN_SCRIPT_BLOCK و STARTUP_SCRIPT_BLOCK و ONSUBMIT_SCRIPT_BLOCK به کلاس RichTextEditor اضافه می کنیم که حاوی اسکریپ های مورد نظر ما جهت ثبت کردن در صفحه هستند:

protected const string CLIENT_SCRIPT_BLOCK = @"
function turnOnDesignMode(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.designMode = 'on';
}
function loadContent(sSElmId, sDElmId) {
var oIFrame = document.getElementById(sSElmId);
var oHiddenField = document.getElementById(sDElmId);
oHiddenField.value = oIFrame.contentWindow.document.body.innerHTML;
}
function setToBold(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.execCommand('bold', false, null);
}
function setToItalic(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.execCommand('italic ', false, null);
}
function setToUndeline(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.execCommand('underl ine', false, null);
}
";

protected const string STARTUP_SCRIPT_BLOCK = @"
setTimeout(""turnOnDesignMode('{iframeId}');"", 10);
";

protected const string ONSUBMIT_SCRIPT_BLOCK = @"
loadContent('{iframeId}', '{inputId}');
";
سپس متد OnPreRender را به شکل زیر بازنویسی کنید:

protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);

string iframeId = "iframe_" + this.ID;

Page.ClientScript.RegisterStartupScript(this.GetTy pe(), this.ID, STARTUP_SCRIPT_BLOCK.Replace("{iframeId}", iframeId), true);
Page.ClientScript.RegisterClientScriptBlock(this.G etType(), "RichTextEditor", CLIENT_SCRIPT_BLOCK, true);
Page.ClientScript.RegisterOnSubmitStatement(this.G etType(), this.ID, ONSUBMIT_SCRIPT_BLOCK.Replace("{iframeId}", iframeId).Replace("{inputId}", this.ID));
}

مرحله ی هشتم: بازنویسی متد RenderContents
کار اصلی یک کنترل سمت سرور این است که کدهای HTML را به جریان خروجی HTTP بفرستد تا در نهایت در سمت مشتری نمایش داده شوند. وظیفه ی ما به عنوان توسعه دهنده این است که به کنترل سمت سرور بگوییم چه کدهایی را باید بفرستد.
متد بازنویسی شده ی RenderContents جای اصلیست که در آن ما باید به کنترل بگوییم چه کدهایی را می خواهیم به سمت مشتری بفرستد. متد بازنویسی شده ی RenderContents زیر را به کلاس RichTextEditor اضافه کنید:
protected override void RenderContents(HtmlTextWriter output)
{

}
دقت کنید که متد RenderContents یک پارامتر با نام output دارد. این پارامتر یک شی از نوع HtmlTextWriter می باشد که کنترل از آن برای ارائه کد HTML خود به مشتری استفاده می کند. کلاس HtmlTextWriter متد هایی شامل AddAttribute و RenderBeginTag را برای ایجاد کد های HTML در اختیار شما قرار می دهد.


مرحله ی نهم: ایجاد کد های HTML
ادیتور مورد نظر ما، از یک iframe به همراه سه عدد input از نوع button تشکیل شده است. همچنین از یک input از نوع hidden به منظور ارسال محتویات ادیتور به سرور استفاده خواهیم کرد. همانطور که قبلا اشاره شد، نام این المنت مشابه با نام کنترل ما در سمت سرور می باشد.
برای ایجاد تگ های ابتدایی و انتهایی هر المنت به ترتیب از متد های RenderBeginTag و RenderEndTag استفاده خواهیم کرد. همچنین برای اضافه کردن ویژگی های هر المنت از متد AddAttribute پیش از فراخوانی متد های ذکر شده در بالا استفاده می کنیم.
در نهایت متد RenderContents به شکل زیر بازنویسی خواهد شد:

protected override void RenderContents(HtmlTextWriter output)
{
Page.VerifyRenderingInServerForm(this);

string iframeId = "iframe_" + this.ID;

output.AddAttribute("id", iframeId);
output.RenderBeginTag("iframe");
output.RenderEndTag();

output.AddAttribute("type", "hidden");
output.AddAttribute("id", this.ID);
output.AddAttribute("name", this.UniqueID);
output.RenderBeginTag("input");
output.RenderEndTag();

output.RenderBeginTag("br");

output.AddAttribute("type", "button");
output.AddAttribute("value", "Bold");
output.AddAttribute("onclick", string.Format("setToBold('{0}')", iframeId));
output.RenderBeginTag("input");
output.RenderEndTag();

output.AddAttribute("type", "button");
output.AddAttribute("value", "Italic");
output.AddAttribute("onclick", string.Format("setToItalic('{0}')", iframeId));
output.RenderBeginTag("input");
output.RenderEndTag();

output.AddAttribute("type", "button");
output.AddAttribute("value", "Underline");
output.AddAttribute("onclick", string.Format("setToUndeline('{0}')", iframeId));
output.RenderBeginTag("input");
output.RenderEndTag();
}

مرحله دهم: حذف تگ Span
هنگامی که ما کنترل خود را به کد های HTML تبدیل می کنیم به طور پیشفرض ASP.NET آن ها را در یک تگ span قرار خواهد داد. این تگ به صورت پیشفرض دارای شناسه ای مشابه با شناسه ی کنترل ما می باشد. و از آنجایی که این شناسه همان شناسه ی تگ input از نوع hidden ما که برای ارسال اطلاعات استفاده کرده بودیم می باشد، وجود این تک باعث ایجاد اشکال در کار کنترل و کدهای صفحه خواهد شد. برای جلوگیری از اضافه شدن این تگ متد Render را نیز بازنویسی خواهیم کرد.

protected override void Render(HtmlTextWriter writer)
{
this.RenderContents(writer);
}
در نهایت پس از اعمال تغییرات کدهای ما باید به شکل زیر باشند:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Specialized;

namespace CustomControls
{
[ToolboxData("<{0}:RichTextEditor runat=server></{0}:RichTextEditor>")]
public class RichTextEditor : WebControl, IPostBackDataHandler
{
protected const string CLIENT_SCRIPT_BLOCK = @"
function turnOnDesignMode(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.designMode = 'on';
}
function loadContent(sSElmId, sDElmId) {
var oIFrame = document.getElementById(sSElmId);
var oHiddenField = document.getElementById(sDElmId);
oHiddenField.value = oIFrame.contentWindow.document.body.innerHTML;
}
function setToBold(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.execCommand('bold', false, null);
}
function setToItalic(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.execCommand('italic ', false, null);
}
function setToUndeline(sElmId) {
var oIFrame = document.getElementById(sElmId);
oIFrame.contentWindow.document.execCommand('underl ine', false, null);
}
";

protected const string STARTUP_SCRIPT_BLOCK = @"
setTimeout(""turnOnDesignMode('{iframeId}');"", 10);
";

protected const string ONSUBMIT_SCRIPT_BLOCK = @"
loadContent('{iframeId}', '{inputId}');
";

public string InnerHTML
{
get
{
string text = ViewState["InnerHTML"] as string;
return string.IsNullOrEmpty(text) ? string.Empty : text;
}

set
{
ViewState["InnerHTML"] = value;
}
}

public bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
string postedValue = postCollection[postDataKey];
InnerHTML = postedValue;
return false;
}

public virtual void RaisePostDataChangedEvent()
{

}

protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);

string iframeId = "iframe_" + this.ID;

Page.ClientScript.RegisterStartupScript(this.GetTy pe(), this.ID, STARTUP_SCRIPT_BLOCK.Replace("{iframeId}", iframeId), true);
Page.ClientScript.RegisterClientScriptBlock(this.G etType(), "RichTextEditor", CLIENT_SCRIPT_BLOCK, true);
Page.ClientScript.RegisterOnSubmitStatement(this.G etType(), this.ID, ONSUBMIT_SCRIPT_BLOCK.Replace("{iframeId}", iframeId).Replace("{inputId}", this.ID));
}

protected override void RenderContents(HtmlTextWriter output)
{
Page.VerifyRenderingInServerForm(this);

string iframeId = "iframe_" + this.ID;

output.AddAttribute("id", iframeId);
output.RenderBeginTag("iframe");
output.RenderEndTag();

output.AddAttribute("type", "hidden");
output.AddAttribute("id", this.ID);
output.AddAttribute("name", this.UniqueID);
output.RenderBeginTag("input");
output.RenderEndTag();

output.RenderBeginTag("br");

output.AddAttribute("type", "button");
output.AddAttribute("value", "Bold");
output.AddAttribute("onclick", string.Format("setToBold('{0}')", iframeId));
output.RenderBeginTag("input");
output.RenderEndTag();

output.AddAttribute("type", "button");
output.AddAttribute("value", "Italic");
output.AddAttribute("onclick", string.Format("setToItalic('{0}')", iframeId));
output.RenderBeginTag("input");
output.RenderEndTag();

output.AddAttribute("type", "button");
output.AddAttribute("value", "Underline");
output.AddAttribute("onclick", string.Format("setToUndeline('{0}')", iframeId));
output.RenderBeginTag("input");
output.RenderEndTag();

}

protected override void Render(HtmlTextWriter writer)
{
this.RenderContents(writer);
}
}
}


مرحله یازدهم: ساخت پروژه
حال زمان ساختن پروژه فرا رسیده است. گزینه ی Build Solution را از منوی Build اجرا کنید.
بعد از ساختن پروژه، قدم بعدی ما اضافه کردن کنترل مورد نظر به بخش Toolbox Explorer می باشد.


84704


مرحله دوازدهم: افزودن کنترل RichTextEditor به تول باکس ویژوال استودیو
برای اضافه کردن این کنترل به تول باکس، بر روی Toolbox Explorer کلیک راست کنید و سپس Choose Items را از منوی ظاهر شده انتخاب کنید. سپس بر روی دکمه Browse از پنجره ی باز شده کلیک کنید. در پنجره ی باز شده به پوشه ی ای که پروژه کنترل سفارشی در آن قرار دارد رفته و به مسیر CustomControls\Bin\Debug بروید. سپس فایل CustomControls.dll را انتخاب کرده و بر روی دکمه ی Open کلیک کنید. کنترل مورد نظر به تول باکس اضافه خواهد شد و با دابل کلیک بر روی آن می توانید به سادگی آن را به صفحه ی خود اضافه کنید.


84707

دانلود سورس پروژه ی آموزشی (فقط شامل مطالب آموز داده شده در همین پست):

clover
دوشنبه 07 فروردین 1391, 15:14 عصر
رزرو برای فهرست

clover
سه شنبه 08 فروردین 1391, 23:25 عصر
طراحی قالب و اضافه شدن فایل CSS قالب و عکس ها به پروژه
اضافه شدن دکمه های مربوط به تراز متن
اضافه شدن ویژگی های Width و Height جهت تنظیم طول و عرض

دانلود پروژه:

clover
چهارشنبه 09 فروردین 1391, 15:38 عصر
بهینه سازی کدهایی جاوا اسکریپت و متد Render
افزودن استایل ها و اسکریپت ها در قالب Web Resource





دانلود پروژه:

clover
یک شنبه 20 فروردین 1391, 23:19 عصر
افزوده شدن امکان انتخاب فونت و سایز متن






دانلود پروژه:

sasanrstm
پنج شنبه 31 فروردین 1391, 22:10 عصر
سلام وخسته نباشي دوست خوبم من اين اديتور 4 شمارو تو يه برنامه گذاشتم ويه دگمه و يه تكست كه متن نوشته شده را تو تكست نشون بده اما وقتي رو راست چين كردن كلمات كليك ميكنم خطاي زير وميده علت اين خطا چي ميتونه باشه در ضمن اگه امكان داره آموزش درست كردن اديتور شكلك را هم بزاريد ممنون از زحمات شما اينم خطائي كه ميده ؟؟
A potentially dangerous Request.Form value was detected from the client (RichTextEditor1$Input="<div style="text-ali...").

clover
پنج شنبه 31 فروردین 1391, 22:27 عصر
سلام وخسته نباشي دوست خوبم من اين اديتور 4 شمارو تو يه برنامه گذاشتم ويه دگمه و يه تكست كه متن نوشته شده را تو تكست نشون بده اما وقتي رو راست چين كردن كلمات كليك ميكنم خطاي زير وميده علت اين خطا چي ميتونه باشه در ضمن اگه امكان داره آموزش درست كردن اديتور شكلك را هم بزاريد ممنون از زحمات شما اينم خطائي كه ميده ؟؟
A potentially dangerous Request.Form value was detected from the client (RichTextEditor1$Input="<div style="text-ali...").

سلام دوست عزیز
در حالت عادی و به دلیل مسائل امنیتی ASP.NET به شما اجازه نمیده که بتونید متن حاوی تگ ها رو به سرور ارسال کنید و از اونجایی که متن تولید شده توسط ادیتور شامل تگ های HTML هست با خطای فوق مواجه میشید.
راه حل ابتدایی این هست که در صفحه ی مربوطه ValidateRequest رو غیر فعال کنید (همونطور که در صفحه ی نمونه من این کار رو انجام دادم):

<%@ Page Language="C#‎" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" ValidateRequest="False" %>

اما به زودی قابلیت رمز گذاری HTML رو به ادیتور اضافه می کنم تا این مشکل حل بشه.

موفق باشید

Mcraft
پنج شنبه 14 اردیبهشت 1391, 12:43 عصر
سلام خسته نباشید.
اگر امکانش هست vb رو هم بگید.
خدا قوت...

ASP.NET2
پنج شنبه 14 اردیبهشت 1391, 19:27 عصر
سلام
عالی بود
از اونجایی که همه اطلاع دارن مشکل عمده Editor ها که ما باهاشون کار میکنیم نداشتن RTL و LTR هستش .که برا ما که از زبان فارسی و انگلیسی در متن هامون استفاده میکنیم خیلی مهمه برا همینه که خیلی ها TinyMce رو ترجیح میدن. چون این خاصیت ها رو داره.
در مقابل برای اینکه بتونی از خاصیت مدیریت فایل و تصاویر در Tinymce استفاده کنی میبایست افزونه اون رو بخری به قیمت :€900 که قیمت بالایی هستش.
در ضمن چون Tinymce از کد های javascript سمت کلاینت استفاده میکنه با َAjax هم مشکل داره.
به نظر من اگه بشه ادیتوری که شما زحمتش رو کشیدی توسعه داد و این خاصیت ها رو بهش اضافه کرد ،میتونه خیلی زیاد مورد استقبال قرار بگیره.
بازهم باید از کار مفیدتون تشکر کرد.
امیدوارم این پست بتونه موجب دلگرمی شما باشه برا توسعه کارتون

bitcob589
جمعه 05 خرداد 1391, 19:37 عصر
با سلام
در هنگامی ادیتور به صفحه اضافه می شود خطای زیر می دهد

The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).

clover
پنج شنبه 11 خرداد 1391, 17:43 عصر
افزوده شدن قابلیت انتخاب جهت متن (راست به چپ یا بالعکس)

clover
سه شنبه 16 خرداد 1391, 00:01 صبح
- قابلیت قالب بندی جعبه ابزار
- رفع باگ و بروز رسانی کدهای جاوا اسکریپت



87891




<CC:RichTextEditor ID="RichTextEditor1" runat="server" Height="200" Width="300">
<Toolbar>
<CC:Toolbox>
<CC:DropDownList Type="FontName" />
<CC:DropDownList Type="FontSize" />
<CC:LineBreak />
<CC:Button CommandName="Bold" />
<CC:Button CommandName="Italic" />
<CC:Button CommandName="Underline" />
<CC:Button CommandName="StrikeThrough" />
</CC:Toolbox>
<CC:Separator />
<CC:Toolbox>
<CC:Button CommandName="AlignLeft" />
<CC:Button CommandName="AlignCenter" />
<CC:Button CommandName="AlignRight" />
<CC:Button CommandName="Justify" />
<CC:LineBreak />
<CC:Button CommandName="LeftToRight" />
<CC:Button CommandName="RightToLeft" />
</CC:Toolbox>
</Toolbar>
</CC:RichTextEditor>


دانلود:

ramin149
سه شنبه 16 خرداد 1391, 12:50 عصر
دوست عزیز اگر به برنامتون دو امکان تغییر رنگ متن و آپلود عکس رو هم قرار بدید . من دیگه از Editor شما در پروژه هام استفاده می کنم .

clover
سه شنبه 16 خرداد 1391, 18:38 عصر
دوست عزیز اگر به برنامتون دو امکان تغییر رنگ متن و آپلود عکس رو هم قرار بدید . من دیگه از Editor شما در پروژه هام استفاده می کنم .
البته این ادیتور هنوز آزمایشی هست و باگ های بسیار زیادی داره و حتی با اضافه شدن امکانات بیشتر قابلیت استفاده در پروژه های واقعی رو نداره اما به زودی امکانات این ادیتور افزایش پیدا خواهد کرد و امکاناتی مثل تغییر رنگ متن و افزودن لینک و عکس هم اضافه میشه.
آپلود عکس خودش نیازمند یه کنترل جدا هست که فکر نمی کنم به این زودی ها آماده بشه.

موفق باشید

h.rezaee
چهارشنبه 24 خرداد 1391, 18:12 عصر
سلام. من هم از این کارتون خوشم اومد منتظر بقیه هم هستیم.

leilaebrahimi
پنج شنبه 30 خرداد 1392, 12:12 عصر
سلام. میشه برای زبان vb هم تبدیل اش کرد یا نه؟

fakhravari
پنج شنبه 30 خرداد 1392, 13:16 عصر
سلام. میشه برای زبان vb هم تبدیل اش کرد یا نه؟
کد های c# به vb تبدیل کنید. تبدیل کنندش زیاد هست.

fakhravari
پنج شنبه 30 خرداد 1392, 13:18 عصر
RichTextEditor در حالت error creating control هست. ولی کار میکنه.

r_s1389@yahoo.com
پنج شنبه 30 خرداد 1392, 13:35 عصر
با زبان vb میتونید بنویسید

fakhravari
پنج شنبه 30 خرداد 1392, 16:15 عصر
با زبان vb میتونید بنویسید
سوال ،جواب، چی گفتی!:بامزه: