PDA

View Full Version : Write كردن يه كنترل در زمان لود



mehrdad_shahian
شنبه 16 بهمن 1389, 10:28 صبح
سلام
من يه string دارم كه حاوي <table border="1" width="100%"><tr><td><-ABC-></td></tr></table>

هستش كه مي خام به جاي <-ABC-> يه يوزر كنترل به اين شكل قرار بدم <uc1:A ID="A1" runat="server" />

و بعد با دستور Response.Write رايتش كنم در رويداد Page_PreRender حال اگه راه حلي هست لطفا بگيد

با تشكر پيشاپيش از همه

raziee
شنبه 16 بهمن 1389, 11:11 صبح
دلیل اینکه نمایش نمیده کاملا واضحه.
شما قصد دارید یک کنترل سمت سرور رو در خروجی بنویسید که برای مرورگر ها هیچ معنایی نداره.
کنترل های سمت سرور ، رندر شده و به یک کد HTML تبدیل میشوند.
مرورگر های چیزی جز HTML رو نمیتونند پردازش کنند.(البته منظور JS,CSS,... نیست!)



حال برای کار شما:
هر کنترل دات نت میتونه Child Control داشته باشند.
یعنی میتونید در یک کنترل ، یک کنترل دیگه اضافه کنید.

به عنوان مثال یک Place Holder در صفحه بگذارید و به این کنترل ، کنترل های دیگه رو اضافه کنید.



Button myButton = new Button();
myButton.Text = "Test";
myButton.Click += new EventHandler(myButton_Click);
myPlaceHolder.Controls.Add(myButton);

و برای اضافه کردن رویداد


void myButton_Click(object sender, EventArgs e)
{
Response.Write("Button Clicked");
}

Javad_Darvish_Amiry
شنبه 16 بهمن 1389, 11:13 صبح
یعنی منظورتون اینه که میخواید که خود نوشته فوق رو بدون هیچ تغییری بنویسید دیگه درسته؟
اگه اینطوره به خاطر وجود کاراکتر های < و > هست که نمایش داده نمیشه. چون مرورگر با دیدن این کاراکترها فکر میکنه با تگ html طرفه و سعی میکنه رندرشون کنه که البته چون این تگ ها رو نمیشناسه با خطا مواجه میشه و چون خطا تو درک دستورات و تگ های html همیشه ignore میشه به سادگی از کنارشون میگذره. شما برای نوشتن رشته فوق طوری که مرورگر نشونش بده باید کد کاراکتر های مورد نظر رو بنویسی. یعنی جمله فوق رو به صورت زیر اصلاح کنید درست میشه (البته عرض کردم؛ اگه درست متوجه منظورتون شده باشم):


&lt;asp:Button ID='Button1' runat='server' Text='Button' /&gt;

موفق باشید.

mehrdad_shahian
شنبه 16 بهمن 1389, 11:21 صبح
یعنی منظورتون اینه که میخواید که خود نوشته فوق رو بدون هیچ تغییری بنویسید دیگه درسته؟
اگه اینطوره به خاطر وجود کاراکتر های < و > هست که نمایش داده نمیشه. چون مرورگر با دیدن این کاراکترها فکر میکنه با تگ html طرفه و سعی میکنه رندرشون کنه که البته چون این تگ ها رو نمیشناسه با خطا مواجه میشه و چون خطا تو درک دستورات و تگ های html همیشه ignore میشه به سادگی از کنارشون میگذره. شما برای نوشتن رشته فوق طوری که مرورگر نشونش بده باید کد کاراکتر های مورد نظر رو بنویسی. یعنی جمله فوق رو به صورت زیر اصلاح کنید درست میشه (البته عرض کردم؛ اگه درست متوجه منظورتون شده باشم):


&lt;asp:Button ID='Button1' runat='server' Text='Button' /&gt;

موفق باشید.
نه خير دوست عزيز،من ميخام خود كنترل اضافه بشه به صفحه و خود كنترل رو نمايش بده

mehrdad_shahian
شنبه 16 بهمن 1389, 11:22 صبح
من تاپيك رو اصلاح كردم

Javad_Darvish_Amiry
شنبه 16 بهمن 1389, 11:58 صبح
بر فرض شما یه کنترل با تعریف زیر تو پوشه Controls ساختید:


<%@ Control className="MyUserControl" %>

یعنی اسم کنترل رو گذاشتید: MyUserControl
اول یه ریفرنس به کنترل تو صفحه ای که میخواید ازش استفاده کنید میدید (درست مثل استفاده از یوزرکنترل ها در حالت معمولی):


<%@ Reference Control="~/Controls/MyUserControl.ascx" %>

بعد به جای ABC که بالا ذکر فرمودید یه کنترل هولدر که بهترینشون تو این حالت PlaceHolder هست اضافه کنید:


<table border="1" width="100%"><tr><td>
<asp:PlaceHolder runar="server" ID="MyHolder" />
</td></tr></table>

حالا میرید تو قسمت کدبیهایند. اول یه فیلد از تایپ یوزرکنترلتون به کلاس کدبیهایند اضافه کنید:


protected MyUserControl _myControl;

و بعد تو رویداد پیج-لود (یا هر رویداد دیگه ای که مناسب با کاربردتون باشه) کد زیر رو اضافه بفرمایید:


protected void Page_Load(object sender, EventArgs e)
{
if(!this.Page.IsPostBack){
_myControl = this.LoadControl("~/Controls/MyUserControl.ascx") as MyUserControl;
// Set values for your Control.
MyHolder.Controls.Add(_myControl);
}
}

موفق باشید.

raziee
شنبه 16 بهمن 1389, 12:39 عصر
من تاپيك رو اصلاح كردم
دوست من ، فکر نمیکنم این شیوه ی ویرایش پست صحیح باشه!!!
شما کل متن سوالتون رو عوض کردید.
جواب هایی که تا اینجا داده شد با توجه به اون سوال بود.
بهتر بود یک پست جدید میزدید و سوال خودتون رو واضح تر مطرح میکردید.
اینجوری دیگه خوانندگان بعدی این تاپیک گمراه نمیشدند.

اما برای سوال جدیدتون(یا منظور اصلیتون)
من قبلا سوال مشابه ای رو پرسیده بودم.

این تاپیک (http://barnamenevis.org/showthread.php?231858) رو مطالعه کن ببین به نتیجه ای میرسی.

mehrdad_shahian
شنبه 16 بهمن 1389, 17:19 عصر
Javad_Darvish_Amiryاز اينكه جواب داديد متشكرم، من كد رو امتحان كردم و به MyHolder اشكال ميگيره وميگه كه تعريف نشده و نميگزاره كه برنامه اجرا بشه.
بعد من ميخام كل رشته حاوي table border="1" width="100%"><tr><td><-ABC-></td></tr></table> رو نمايش بدم.يعني جدول رو نشون بدم به اضافه يوزر كنترلي كه بهش اضافه شده.

mehrdad_shahian
شنبه 16 بهمن 1389, 17:30 عصر
دوست من ، فکر نمیکنم این شیوه ی ویرایش پست صحیح باشه!!!
شما کل متن سوالتون رو عوض کردید.
جواب هایی که تا اینجا داده شد با توجه به اون سوال بود.
بهتر بود یک پست جدید میزدید و سوال خودتون رو واضح تر مطرح میکردید.
اینجوری دیگه خوانندگان بعدی این تاپیک گمراه نمیشدند.

اما برای سوال جدیدتون(یا منظور اصلیتون)
من قبلا سوال مشابه ای رو پرسیده بودم.

این تاپیک (http://barnamenevis.org/showthread.php?231858) رو مطالعه کن ببین به نتیجه ای میرسی.
ممنون حق با شماست.
ولي در رابطه با تاپيكي كه گذاشته ايد،در آخر شما همان سوال من رو پرسيديد ولي جواب درستي من نديدم و پاسخي به تاپيك داده نشده و من نميدوتم چرا شما تشكر كرديد.من كه جواب نگرفتم

Javad_Darvish_Amiry
شنبه 16 بهمن 1389, 18:40 عصر
یعنی منظورتون اینه که رشته <table border="1" width="100%"><tr><td><-ABC-></td></tr></table> هم در صفحه وجود نداره و شما میخواید تو runtime بسازیدش؟!
اگه اینطور هست باید این کنترل ها رو هم مثل کنترل های بالا زمان اجرا ایجاد کنید. اما نمیتونید بنویسیدش. بلکه در هر صورت باید یه کانتینر تو صفحه داشته باشید که این کنترل ها رو به اون اضافه کنید. اگه منظورتون رو درست متوجه شدم بگید که کدش رو بنویسم.

mehrdad_shahian
شنبه 16 بهمن 1389, 18:59 عصر
یعنی منظورتون اینه که رشته <table border="1" width="100%"><tr><td><-ABC-></td></tr></table> هم در صفحه وجود نداره و شما میخواید تو runtime بسازیدش؟!
اگه اینطور هست باید این کنترل ها رو هم مثل کنترل های بالا زمان اجرا ایجاد کنید. اما نمیتونید بنویسیدش. بلکه در هر صورت باید یه کانتینر تو صفحه داشته باشید که این کنترل ها رو به اون اضافه کنید. اگه منظورتون رو درست متوجه شدم بگید که کدش رو بنویسم.

بله اينيكه شما ميگيد وجود نداره درسته،اين رشته از يه فيلد در ديتابيس خونده ميشه،من ميخام در موقع لود كردن صفحه اين رشته رو رايت كنم،در واقع <-ABC-> رو تو رشته پيدا كنم و يه يوزر كنترلي رو جايگزين اين بكنم و در اخر جدول و يوزر كنترل رو نمايش بدم.
يعني هر جا <-ABC-> رو ديد يه يوزر كنترل به جاش قرار بده.

Javad_Darvish_Amiry
شنبه 16 بهمن 1389, 19:19 عصر
خوب حالا گرفتم (همیشه بهترین جوابها رو در مقابل بهترین شکل پرسیدن دریافت میکنیم). برای اینکار مرحله اول مانند پستیه که قبلا فرستادم. یعنی یوزر-کنترل باید لود بشه و مقداردهی (در صورت نیاز) انجام بشه. اما دیگه نیاز نیست به PlaceHolder ی اضافه بشه. بلکه تو این وضعیت باید رندر بشه و از رندر شدنش یه استرینگ به دست میاد. حالا این استرینگ با <-ABC-> با کمک متود Replace کلاس استرینگ یا با رگولار اکسپرسشن تعویض بشه. با داشتن اطلاعات از پست قبلی میشه اون مثال رو به شکل زیر اصلاح کرد تا منظور شما برآورده بشه:


String txt = @"<table border=""1"" width=""100%""><tr><td><-ABC-></td></tr></table>";

_myControl = this.LoadControl("~/Controls/MyUserControl.ascx") as MyUserControl;

TextWriter myTextWriter = new StringWriter();
HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter);

_myControl.RenderControl(myWriter);

String result = myTextWriter.ToString();

txt = txt.Replace("<-ABC->", result);
الان ما توی متغیر txt استرینگ نهایی رو داریم که شما میتونید هر جایی اونو بنویسید. موفق باشید.

mehrdad_shahian
شنبه 16 بهمن 1389, 19:38 عصر
مرسي از جواب و نكته پند آموزتون.
به TextWriter گير ميده؟using مي خاد؟

Javad_Darvish_Amiry
شنبه 16 بهمن 1389, 19:45 عصر
خواهش میکنم. آره. فضای نام System.IO رو اضافه کنید.

mehrdad_shahian
شنبه 16 بهمن 1389, 19:47 عصر
متوجه شدم using System.IO; رو بايد اضافه كرد.

نكته بعدي اينكه اگه يوزر كنترل حاوي يه متن ساده باشه جواب ميده ولي اگه يوزر كنترل ما حاوي كنترل هاي سروري مانند Botton باشه Error ميده.
به اين خط كه ميرسه _myControl.RenderControl(myWriter);
اين Error رو ميده Control 'Button1' of type 'Button' must be placed inside a form tag with runat=server.

Javad_Darvish_Amiry
شنبه 16 بهمن 1389, 21:03 عصر
فکر میکنم بدونم به خاطر چیه. اما اجازه بدید ویندوزم رو نصب کنم و تست کنم. بعد خدمتتون عرض میکنم. الان مطمئن نیستم. (الان ده دوازده روزه ویندوز ندارم اما امشب حتما راش میندازم) موفق باشید.

mehrdad_shahian
یک شنبه 17 بهمن 1389, 08:58 صبح
مرسی فقط کار من یه خورده عجله ای اگه میشه زودتر راش بندازید.بازم میگم متشکرم

مهدی کرامتی
یک شنبه 17 بهمن 1389, 13:19 عصر
فرض کنید یک UserControl به نام MyUserControl.ascx دارید که در فولدری به نام UserControls قرار دارد (در این روش مهم است که UserControl در همان فولدری که صفحه قرار دارد نباشد، وگرنه خطا دریافت خواهید کرد).

در Web.Config در تگ pages کنترل فوق را معرفی کنید، مثلا:

<pages>
<controls>
<add tagPrefix="uc1" src="~/UserControls/MyUserControl.ascx" tagName="MyUserControl"/>
</controls>
</pages>توجه: تگ pages زیر مجموعه <system.web> است و میبایست بین <system.web> و <system.web/> قرار بگیرد.

در صفحه مورد نظر این کد را برای لود کردن UserControl به صورت Runtime استفاده کنید:

string control_tag = @"<table border='1' width='100%'><tr><td>
<uc1:MyUserControl ID='MyUserControl1' runat='server' />
</td></tr></table>";

Control myCompositeControl = Page.ParseControl(control_tag);

this.Form.Controls.Add(myCompositeControl);هما طورکه خواهید دید در این روش PostBack های UserControl نیز کار خواهند کرد.

پروژه نمونه ضمیمه شده است.

mehrdad_shahian
یک شنبه 17 بهمن 1389, 18:53 عصر
سلام خدمت اقاي DelphiAssistant
متشكرم از اينكه جواب داديد.
اين نمونه مثالي كه گذاشنيد با چه ورژني از ويژوال استوديو نوشته شده.چون من نتونستم اجراش كنم و به اين targetFramework="4.0" گير ميده
لطفا مشكل رو برطرف كنيد

mehrdad_shahian
یک شنبه 17 بهمن 1389, 19:04 عصر
بعدا من كارايي كه گفتيد رو انجام دادم ولي به اين ارور بخوردم
Control 'MyUserControl1_Button1' of type 'Button' must be placed inside a form tag with runat=server.


ولي اگه يوزر كنترل ساده باشه و حاوي كليد نباشه جواب ميده

Javad_Darvish_Amiry
یک شنبه 17 بهمن 1389, 19:30 عصر
نکته ای که اقای DelphiAssistant گفتند کارتون رو باید راه بندازه. اما متود ParseControl فقط تو دات نت ۳.۵ و ۴ وجود داره. نمیدونم معادلی تو ورژن های پایین تر داره یا نه. اگه شما ملزم به استفاده از ورژن های پایینتر نیستید تارگت رو ارتقاء بدید درست میشه. (برای این کار رو پروژه راست کلیک کنید -رو پروژه نه سلوشن- و پراپرتی رو انتخاب کنید). اگه نه باید قید پست-بک و ویو استیت رو بزنید و در صورت نیاز خودتون باید به صورت دستی رویداد ها رو کنترل کنید.اگه هم نه باید رشته دریافتی از پایگاه رو پارس کنید و تمامش رو تبدیل به کنترل کنید و به روشی که اول توضیح داده بودم کار کنید. حالا شما انتخاب کنید کدوم روش مناسبه تا رو اون کار کنیم. موفق باشید.

mehdi.mousavi
یک شنبه 17 بهمن 1389, 19:45 عصر
[COLOR=black]اما متود ParseControl فقط تو دات نت ۳.۵ و ۴ وجود داره.

سلام.
TemplateControl.ParseControl در .NET Framework 1.0 نیز وجود داشتش، اون overload دوم این تابع هستش که در پارامتر دومش یه flag میگیره و در NET 2.0 SP1. به بعد به Framework اضافه شدش.
کد آقای کرامتی نیز از Overload اولی استفاده میکنه، در نتیجه در .NET 1.0 نیز قابل استفاده هستش.

موفق باشید.

Javad_Darvish_Amiry
یک شنبه 17 بهمن 1389, 20:08 عصر
سلام. مرثی از راهنماییتون. حق با شماست. این ساپورت خود msdn هستش تو این آدرس (http://msdn.microsoft.com/en-us/library/bb559279%28v=VS.90%29.aspx).

Version Information
.NET Framework

Supported in: 3.5 SP1, 3.0 SP1, 2.0 SP1

مهدی کرامتی
یک شنبه 17 بهمن 1389, 20:28 عصر
اين نمونه مثالي كه گذاشنيد با چه ورژني از ويژوال استوديو نوشته شده.چون من نتونستم اجراش كنم و به اين targetFramework="4.0" گير ميده
پروژه با ویژوال استودیو 2010 نوشته شده، اما دستورالعمل ها در همه ورژن های ویژوال استودیو قابل اعمال و استفاده است.

بعدا من كارايي كه گفتيد رو انجام دادم ولي به اين ارور بخوردم
Control 'MyUserControl1_Button1' of type 'Button' must be placed inside a form tag with runat=server.

ولي اگه يوزر كنترل ساده باشه و حاوي كليد نباشه جواب ميده
احتمالا شما Page.Controls.Add را استفاده کرده اید. اگر بجای آن از this.Form.Controls.Add استفاده کنید مشکل برطرف خواهد شد.

mehrdad_shahian
دوشنبه 18 بهمن 1389, 09:34 صبح
احتمالا شما Page.Controls.Add را استفاده کرده اید. اگر بجای آن از this.Form.Controls.Add استفاده کنید مشکل برطرف خواهد شد.

من از form1.Controls.Add(myCompositeControl); استفاده كردم درست شد.

mehrdad_shahian
دوشنبه 18 بهمن 1389, 09:56 صبح
در اخر من از روش اقاي كرامتي استفاده كردم و نتيجه هم گرفتم و كدش رو ميزارم برا بقيه دوستان:

string control_tag = @"<table border='1' width='100%'><tr><td><-A-></td><td><-B-></td><td><-A-></td></tr></table>";
string str="<-A->";
int index = control_tag.IndexOf("<-A->");
int count = 0;
while (index != -1)
{
count++;
control_tag = control_tag.Remove(index, str.Length);
control_tag = control_tag.Insert(index, "<uc1:A ID='A" + count.ToString() + "' runat='server' />");
index = control_tag.IndexOf("<-A->");
}
str = "<-B->";
index = control_tag.IndexOf("<-B->");
count = 0;
while (index != -1)
{
count++;
control_tag = control_tag.Remove(index, str.Length);
control_tag = control_tag.Insert(index, "<uc1:B ID='B" + count.ToString() + "' runat='server' />");
index = control_tag.IndexOf("<-B->");
}
Control myCompositeControl = Page.ParseControl(control_tag);
form1.Controls.Add(myCompositeControl);ولي اي كاش سيستم اقاي اميري راه ميافتاد و از روش ايشون استفاده ميكرديم.چون به نظر من خيلي ساده تر هستش و با يه دستور replace يوزركنترل ها جايگزين ميشن.حالا تا سيستم اقاي اميري راه مي افته كسي هست از دوستان كه از روش ايشون استفاده كرده باشه