نمایش نتایج 1 تا 22 از 22

نام تاپیک: نسبت دادن Event به کنترل های ساخته شده در Runtime

  1. #1

    نسبت دادن Event به کنترل های ساخته شده در Runtime

    سلام دوستان:

    چند تا سوال :

    1 - من دارم یک برنامه می نویسم که با هر بار کلیک روی یک Button یک دیتاگرید روی فرم ایجاد میکنه و اطلاعات یک تیبل از دیتابیس رو نمایش میده اما حالا می خوام روی هر ردیف از هر کدوم ازاین دیتاگرید هایی که تولید میشن کلیک شد اطلاعات اون ردیف داخل یک سری تکست باکس نمایش داده بشن .

    برای این کار از کد زیر استفاده میکنم : (ابتدای کدها یک متغیر از نوع دیتابیس تعریف کردم )


     DataGridView dataGridView = new DataGridView();


            private void dataGridView_CellClick(object sender, GridViewCellEventArgs e)
    {
    textBox3.Text = dataGridView.CurrentRow.Cells[2].Value.ToString();
    textBox4.Text = dataGridView.CurrentRow.Cells[3].Value.ToString();
    textBox5.Text = dataGridView.CurrentRow.Cells[4].Value.ToString();
    textBox6.Text = dataGridView.CurrentRow.Cells[5].Value.ToString();
    textBox7.Text = dataGridView.CurrentRow.Cells[6].Value.ToString();
    textBox8.Text = dataGridView.CurrentRow.Cells[7].Value.ToString();
    textBox10.Text = dataGridView.CurrentRow.Cells[9].Value.ToString();
    }


    و داخل Load فرم هم هنگام ایجاد دیتاگرید ها از این کد استفاده می کنم :

    dataGridView.CellClick += new GridViewCellEventHandler(dataGridView_CellClick);


    اما این ارور رو میده :

    Object reference not set to an instance of an object.


    2- سوال دوم اینکه کنترل هایی که زمان اجرا ساخته میشن رو چطور میشه ذخیره کرد که مجبور نباشیم دوباره هنگام لود همشون رو از اول بسازیم؟ مثلا همین برنامه ای که گفتم اگر چند تا دیتاگرید رو کاربر ایجاد کرد باید دوباره هنگام لود فرم همه رو از اول با یک حلقه بسازم و دوباره اطلاعات دیتابیس رو داخل هر کدوم لود کنم. این کار رو درست انجام دادم ولی خوب لود برنامه رو به مرور سنگین میکنه. کسی راه حل بهتری سراغ نداره ؟

    3- کد Maximize و Minimize کردن فرم رو میخوام که برای دو تا دکمه قرار بدم و همچنین مخفی کردن تمام دکمه های کنترل باکس طوری که قاب فرم قابل نمایش باشه (البته فرم بدون نوشته هست).

    مرسی !
    آخرین ویرایش به وسیله va2012 : چهارشنبه 03 خرداد 1391 در 21:25 عصر

  2. #2
    کاربر دائمی
    تاریخ عضویت
    اردیبهشت 1390
    محل زندگی
    چند قدم اون ور تر
    پست
    1,731

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    سلام
    میشه بگید این همه دیتاگریدویو میخواید چکار؟ کلاً توضیح بدید می خواید چکار کنید شاید راه بهتری هم وجود داشته باشه.

  3. #3

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    همونطور که بالا توضیح دادم این نرم افزار به این صورت هست که برای هر بخش ابتدا یک تیبل داخل دیتابیس ایجاد می کنم و بعد یک دیتا گرید که اطلاعات اون تیبل رو داخل گرید نمایش میدم. یعنی به ازای هر بخشی که ایجاد میشه یک تیبل در دیتابیس میسازم و یک دیتاگرید مجزا برای ثبت و نمایش اطلاعات مربوط به همون تیبل. البته تعداد جدول ها محدودیت داره.

    البته می تونستم اول کار همه بخش ها رو درست کنم و جدول ها رو هم داخل دیتابیس بسازم ولی چون تعداد این بخش ها متغیر هست برای اینکه حجم نرم افزار بالا نره این کار رو انجام دادم.


    من میخوام بدونم کنترل های زمان اجرا رو چطور بایستی ذخیره کرد و چطور براشون رویداد نوشت؟ البته خصوصیاتشون رو با XML ذخیره می کنم ولی میخوام بدونم روشی هست که مجبور به ساخت مجدد کنترل نباشیم؟

    حالا نه فقط واسه این نرم افزار - فرض کنید نرم افزار ما حین اجرا چند تا کنترل رو ایجاد کنه که لازم هست روی فرم باقی بمونن . بهترین راه واسه ذخیره همه این کنترلها چیه؟

  4. #4
    کاربر دائمی
    تاریخ عضویت
    اردیبهشت 1390
    محل زندگی
    چند قدم اون ور تر
    پست
    1,731

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    خب همونطور که گفتید شما باید تک تک خاصیت هایی رو که در کنترل های مورد نظر تغییر میکنند رو ذخیره کنید. فرض کنید یه باتن به فرم اضافه می کنید باید اندازه(Size)، محل قرار گیری(Location)، متن (Text)، رنگ (Back Color و For Color) و ... در یک فایل یا دیتابیس ذخیره کنید بعد موقع لود فرم اونها رو فراخوانی کنید.

  5. #5

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    مرسی . خوب اینا که فرمودین درست ولی با این کار ها هنوز باید کنترل از ابتدا ساخته بشه و بعد از طریق XML یا دیتابیس خصوصیات کنترل ها بازگردانده بشه. ولی منظور من این بود که آیا روشی هست که کنترل های ساخته شده به صورت کامل در قالب همون کنترل به صورت یک سمپل در یک پوشه ذخیره بشن و بعد هنگام اجرای مجدد برنامه از همون پوشه لود بشن.( شبیه کنترل های که در اتوران سازها به صورت template هست). خوب ظاهرا نمیشه . مثل اینکه راه بهتری نیست.

    حالا لطفا در مورد سوال اول اگه راهنمایی دارین بفرمایید.

  6. #6

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    از دوستان کسی می تونه در مورد Event دیتاگرید ها که توی پست اول گفتم راهنمایی کنه؟

  7. #7

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    کسی نیست جواب سوال منو بده؟

  8. #8
    کاربر دائمی آواتار mahdi87_gh
    تاریخ عضویت
    فروردین 1388
    محل زندگی
    قزوین
    پست
    448

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    ابتدا بررسی کنید که CurrentRow برابر null نباشد
    if(null!=dataGridView1.CurrentRow)

  9. #9

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    1 - اگر exception مربوطه در داخل dataGridView_CellClick رخ میده، پس حتما یکی از سلولهای ردیف کلیک شده، مقدارش null هست. اگر اینطور که گفتم باشه، شما باید کد رو بصورت زیر بنویسید:


    private void dataGridView_CellClick(object sender, GridViewCellEventArgs e)
    {
    textBox3.Text = dataGridView.CurrentRow.Cells[2].Value == null ? "" : dataGridView.CurrentRow.Cells[2].Value.ToString();
    textBox4.Text = dataGridView.CurrentRow.Cells[3].Value == null ? "" : dataGridView.CurrentRow.Cells[3].Value.ToString();
    textBox5.Text = dataGridView.CurrentRow.Cells[4].Value == null ? "" : dataGridView.CurrentRow.Cells[4].Value.ToString();
    textBox6.Text = dataGridView.CurrentRow.Cells[5].Value == null ? "" : dataGridView.CurrentRow.Cells[5].Value.ToString();
    textBox7.Text = dataGridView.CurrentRow.Cells[6].Value == null ? "" : dataGridView.CurrentRow.Cells[6].Value.ToString();
    textBox8.Text = dataGridView.CurrentRow.Cells[7].Value == null ? "" : dataGridView.CurrentRow.Cells[7].Value.ToString();
    textBox10.Text = dataGridView.CurrentRow.Cells[9].Value == null ? "" : dataGridView.CurrentRow.Cells[9].Value.ToString();
    }


    2 - شما اطلاعات دیتابیس رو در داخل GridView ها وارد می کنید، خوب اگه این اطلاعات رو ذخیره کنید تا در اجرای بعدی برنامه از اونها استفاده کنید، اگه از instance دیگری از این برنامه یا بطور دستی اطلاعات داخل دینابیس تغییر کنه، شما همچنان با اطلاعات ذخیره شده قدیمی کار خواهید کرد.
    پس کار صحیحی نیست که شما اطلاعات GridView ها رو برای استفاده بعدی ذخیره کنید. در ضمن ساخته شدن control ها در یک loop وقتی نمی گیره، اونی که رمان گیره پر کردن اونها از روی دیتابیس هستش.
    اگر فکر می کنید که فرآیند import اطلاعات داخل GridView ها همچنان سنگین هستش در حالیکه میزان رکوردهای دیتابیس شما خیلی زیاد نیست بهتره کدهای برنامه تون رو بازنگری کنید
    و اگر رکوردهای دیتابیس شما واقعا زیاد هست، می تونید در GridView ها از Pager و Filter استفاده کنید و در هر لحظه فقط بخش مورد نیازتون رو در GridView وارد کنید.

    3-


    // this = current form
    this.WindowState = FormWindowState.Minimized;
    this.WindowState = FormWindowState.Maximized;



    // this = current form
    foreach (Control c in this.Controls)
    {
    if (c is Button)
    c.Visible = false;
    }

  10. #10

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    خیلی ممنون دوستان . انجام دادم ولی هنوز همون ارور رو میده . بذارین من کاملتر توضیح بدم :

    خوب من زمان اجرا میام یک سری کنترل از هر نوعی ( حالا مثلا گرید ویو Telerik ) درست میکنم و اون ها رو به فرم اضافه میکنم . در اینجا همه کنترل ها با نام متغیر dataGridView هست . خوب هر بار که دکمه کلیک بشه یک دیتاگرید جدید با نام جدید درست میشه مثلا dataGridView3و dataGridView2 وdataGridView1 و ... حالا من می خوام برای رویداد CellClick همه این دیتاگرید ها یک رویداد یکسان بنویسم ولی داخل اون متغیر های dataGridView ناشناخته هست. پس من میام و یک instance عمومی از این دیتاگرید میسازم که بتونم در رویداد CellClick به اون کنترل دسترسی داشته باشم و نظرم اینه که مشکل از این ساخت این instance عمومی هست که ارور میده. نمیدونم منظورم رو متوجه شدین یا نه ولی احتمال زیاد مشکل از همین جاست. چرا این رو میگم به خاطر اینکه برای همه گرید های ساخته شده یک رویداد CellFormatting نوشتم و مشکلی نبود. ولی اینجا که نام dataGridView وارد میشه مشکل ایجاد میکنه.


      Telerik.WinControls.UI.RadGridView dataGridView = new Telerik.WinControls.UI.RadGridView();


    اینم instance عمومی که تعریف کردم :

     public partial class MainForm : Form
    {
    Telerik.WinControls.UI.RadGridView dataGridView = new Telerik.WinControls.UI.RadGridView();
    {

  11. #11

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    این قسمت رو کامل متوجه نشدم یعنی چی : "شما اطلاعات دیتابیس رو در داخل GridView ها وارد می کنید، خوب اگه این اطلاعات رو ذخیره کنید تا در اجرای بعدی برنامه از اونها استفاده کنید، اگه از instance دیگری از این برنامه یا بطور دستی اطلاعات داخل دینابیس تغییر کنه، شما همچنان با اطلاعات ذخیره شده قدیمی کار خواهید کرد."

    من جدول های دیتابیس رو دستی هم پر کردم و امتحان کردم همه چیز درست بود و اطلاعات هر جدول رو توی دیتاگرید مربوط به خودش نشون داد. اطلاعات اینقدر زیاد نیست که خیلی طول بکشه .منظور من این بود که وقتی چند تا کنترل در زمان اجرا با خصوصیات مشخص ساخته میشه باید هنگام لود فرم دوباره به همون تعداد کنترل ساخته بشه و خصوصیات هر کنترل به اون برگردونده بشه - آیا این کار که انجام دادم درست هست یعنی راه حل بهت و بهینه تری برای این کار وجود نداره؟

  12. #12

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    نقل قول نوشته شده توسط va2012 مشاهده تاپیک

    من جدول های دیتابیس رو دستی هم پر کردم و امتحان کردم همه چیز درست بود و اطلاعات هر جدول رو توی دیتاگرید مربوط به خودش نشون داد. اطلاعات اینقدر زیاد نیست که خیلی طول بکشه .منظور من این بود که وقتی چند تا کنترل در زمان اجرا با خصوصیات مشخص ساخته میشه باید هنگام لود فرم دوباره به همون تعداد کنترل ساخته بشه و خصوصیات هر کنترل به اون برگردونده بشه - آیا این کار که انجام دادم درست هست یعنی راه حل بهت و بهینه تری برای این کار وجود نداره؟
    بطور کل همیشه میشه ساختار و خصوصیات یک کنترل و حتی اطلاعات داخلش رو در قالب فایل xml ذخیره کرد و دوباره بازخونی کرد.
    اما این یه ذره کار میبره. در ضمن باز هم میگم ساختن چند کنترل در Windows Forms در چند صدم ثانیه انجام میشه، یعنی اگه ساختار و خصوصیات کنترل ها رو هم ذخیره کنید، فکر نکنم بشه بهینه ترش کرد.
    نمیدونم تونستم مفهوم رو برسونم.!

    موفق باشید

  13. #13

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    مرسی من هم نگران همین زمان ساخت کنترل ها بودم که شما میفرمایید زمانی در حد چند صدم ثانیه هست. پس ظاهرا راه حل همین هست و روش بهینه تری نیست. هنوز توی سوال اولم گیر کردم !!!! بازهم همون ارور رو میده

  14. #14

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    OK
    محتوای Stack مربوط به Exception رو اینجا بزارید لطفا تا بفهمم مشکل از کجا می تونه باشه

  15. #15

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    شما پست آخر صفحه قبل رو خوندین من اونجا توضیح دادم ارور به خاطر چی هست : به خاطر این کد هست : فکر کنم برنامه نمیتونه تشخیص بده کدوم dataGridView مورد نظر هست.

       Telerik.WinControls.UI.RadGridView dataGridView = new Telerik.WinControls.UI.RadGridView();


    اینم ارور :

    Object reference not set to an instance of an object


    >	Work Manager v2.exe!Works_Manager_v_1.MainForm.dataGridView_Cel  lClick(object sender, Telerik.WinControls.UI.GridViewCellEventArgs e) Line 684	C#‎‎

  16. #16

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    راست میگی، post آخر صفحه قبل رو ندیده بودم

    شما می تونی از sender برای اشاره به gridview مورد نظر استفاده کنی:


    private void dataGridView_CellClick(object sender, GridViewCellEventArgs e)
    {
    Telerik.WinControls.UI.RadGridView dgv = sender as Telerik.WinControls.UI.RadGridView;
    if (dgv == null)
    return;
    textBox3.Text = dgv.CurrentRow.Cells[2].Value == null ? "" : dgv.CurrentRow.Cells[2].Value.ToString();
    textBox4.Text = dgv.CurrentRow.Cells[3].Value == null ? "" : dgv.CurrentRow.Cells[3].Value.ToString();
    textBox5.Text = dgv.CurrentRow.Cells[4].Value == null ? "" : dgv.CurrentRow.Cells[4].Value.ToString();
    textBox6.Text = dgv.CurrentRow.Cells[5].Value == null ? "" : dgv.CurrentRow.Cells[5].Value.ToString();
    textBox7.Text = dgv.CurrentRow.Cells[6].Value == null ? "" : dgv.CurrentRow.Cells[6].Value.ToString();
    textBox8.Text = dgv.CurrentRow.Cells[7].Value == null ? "" : dgv.CurrentRow.Cells[7].Value.ToString();
    textBox10.Text = dgv.CurrentRow.Cells[9].Value == null ? "" : dgv.CurrentRow.Cells[9].Value.ToString();
    }

  17. #17

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    نه متاسفانه هنوز همون ارور رو میده . باید یکم روش کار کنم شاید درست شد.

    راستی دو تا سوال دیگه : وقتی یک دیتاگرید ویو رو در زمان اجرا ساخته شد و اطلاعات یک جدول داخلش نشون داده شد چطور میشه عرض هر ستون رو تغییر داد؟

    من از این کد معمول استفاده میکنم ولی پیغام میده که ستونی وجود نداره !!!!!!

    dataGridView.Columns[0].Width = 150;


    دوم اینکه چطور یک ستون ردیف برای هر گرید بسازم که با حذف هر سطر از اطلاعات شماره ردیف ها خودکار مرتب بشه چون قبلا برای ستون ردیف از id استفاده می کردم ولی بعد از حذف هر سطر شماره سطر رو از انتهای سطر حذف شده ادامه میده.

  18. #18

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    اگر می خوای مشکل اول رو حل کنی، اینطوری عمل کن
    اگه error در خط اول یعنی:

    textBox3.Text = dataGridView.CurrentRow.Cells[2].Value == null ? "" : dataGridView.CurrentRow.Cells[2].Value.ToString();
    هست، یا textBox3 وجود نداره، یا dataGridView وجود نداره یا CurrentRow نداریم یا CurrentRow.Cell[2] وجود نداره
    که همه رو می تونی در پنجره Watch 1 تست کنی.
    اگر هم error تو بقیه خطوط رخ میده، که مطمئنا ایراد از CurrentRow.Cell[n] هستش، یعنی اون cell خاص وجود نداره

    در مورد سوال اول باید بگم لزوما نباید اطلاعات جدول داخل GridView وارد بشه بعد عرض هر ستون رو تغییر بدی
    اینکار رو میشه در هنگام ساخته شدن هر ستون انجام داد
    هر datagridview یه Event داره شبیه ColumnAdded که در اون می تونی از طریق پارامتر e.Column به ستون ساخته شده دسترسی داشته باشی


    dataGridView.ColumnAdded += new GridViewColumnEventHandler(dataGridView_ColumnAdde d);

    private void dataGridView_ColumnAdded(object sender, GridViewColumnEventArgs e)
    {
    e.Column.Width = 150;
    }
    اگه از RadGridView استفاده می کنی، ممکنه اسامی یه خورده فرق بکنه

    در مورد سوال دوم، اگه در داخل Table مورد نظر، ستون id از نوع Identity باشه (خوبه Primary Key هم باشه)، در اینصورت ستون id همیشه یه شمارنده داره که وقتی سطر جدیدی شروع میشه بر اساس اون شمارنده بهش شماره میده.

  19. #19

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    مرسی ولی TextBox ها همه وجود دارند و این خطا برای همه خط ها اتفاق میفته. همونطور که گفتم احتمالا dataGridView وجود نداره یعنی روی فرم ساخته شده ولی اسمش یه چیز دیگه هست مثلا radGridView1,radGridView2, ...

    اما من همه رو به نام متغیر dataGridView ایجاد کردم . نمیدونم چه راهی هست. میشه یک رویداد رو مستقیما داخل یک حلقه نوشت ؟!!!!!!!!!!!!

    اون رویداد ColumnAdded برای تلریک وجود نداره و من نتونستم معادلش رو پیدادکنم .

    دیتابیس اکسس هست و فکر نکنم ستون id خاصیت Identity داشته باشه یا شاید من نتونستم پیدا کنم.

  20. #20

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    در مورد Column Size می تونی به شکل زیر عمل کنی:

    radGridView.DataBindingComplete +=new Telerik.WinControls.UI.GridViewBindingCompleteEven tHandler(radGridView_DataBindingComplete);

    private void radGridView1_DataBindingComplete(object sender, Telerik.WinControls.UI.GridViewBindingCompleteEven tArgs e)
    {
    Telerik.WinControls.UI.RadGridView dgv = sender as Telerik.WinControls.UI.RadGridView;
    if (dgv.Columns.Count == 0)
    return;
    foreach (Telerik.WinControls.UI.GridViewColumn c in dgv.Columns)
    {
    c.Width = 150;
    }
    }


    در مورد ستون Id در Access هم باید در بخش Design View بری، بعدش Data Type ستون Id رو Auto Number انتخاب کنی و در بخش Field Properties قسمت New Values رو برابر با Increment قرار بدی

    access_Id_autonumber.jpg

  21. #21

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    ممنون از اینکه وقت میذارین و پیگیری می کنید . من هر دو مورد رو امتحان کردم. کد اول که اجرا نمیشه چون ظاهرا تعداد ستون ها رو صفر حساب می کنه و در مورد فیلد ID هم این کار رو همیشه انجام میدم ولی همونطور که قبلا گفتم با حذف یک سطر شماره ها از اول Sort نمیشن. مثلا 5 تا سطر داشتم و سطر 4 رو حذف کردم شماره ها شد : 1-2-3-5 و عدد آخر که 5 هست همونطور باقی موند.

  22. #22

    نقل قول: نسبت دادن Event به کنترل های ساخته شده در Runtime

    در مورد اول لطفا PM تون رو نگاه کنید.
    در مورد دوم، دیتابیس هایی که تا حالا دیدم، همچین کاری نمی کنند
    اما شما می تونی یه ستون دیگه از نوع عددی در نظر بگیری و پس از درج یا خذف یک یا چند ستون در یک مرحله و با استفاده از یک تابع (که مقادیر رو بر اساس ستون Id و بصورت صعودی sort می کنه)، رکوردها رو از 1 الی آخر شماره گذاری کنی.
    البته این کار رو در SQL میشه با استفاده از قابلیت Trigger طوری پیاده سازی کرد که خود SQL این کار رو هر دفعه بصورت اتواتیک انجام بده.
    در ضمن لازمه یادآوری کنم که Id در Table ها مفهوم خاصی داره و اگه بعنوان Primary Key بخواد استفاده بشه، اونوقت میشه شناسه اون جدول و نباید در رکورد خاصی تغییر پیدا کنه!
    خیلی وقتها که از GridView برای نشان دادن محتویات یک جدول استفاده می کنید، وجود ستونی که Primary Key هستش در Event ها خیلی حیاتی هست.

تاپیک های مشابه

  1. اضافه کردن کنترل ها به تب های ساخته شده با jquery
    نوشته شده توسط sara_aryanfar در بخش jQuery
    پاسخ: 15
    آخرین پست: جمعه 22 مهر 1390, 00:17 صبح
  2. اضافه کردن کنترل ها به تب های ساخته شده با jQuery
    نوشته شده توسط sara_aryanfar در بخش ASP.NET Web Forms
    پاسخ: 6
    آخرین پست: پنج شنبه 21 مهر 1390, 22:21 عصر
  3. نسبت دادن Event های WPF و WinForm
    نوشته شده توسط soheilajoon در بخش WPF
    پاسخ: 4
    آخرین پست: دوشنبه 12 مرداد 1388, 20:02 عصر
  4. پاسخ: 2
    آخرین پست: جمعه 15 آبان 1383, 11:53 صبح
  5. کار با کنترل های ایجاد شده در زمان اجرا
    نوشته شده توسط داش اکل در بخش ASP.NET Web Forms
    پاسخ: 9
    آخرین پست: یک شنبه 24 اسفند 1382, 23:17 عصر

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •