گفتگو هایی در باب سی شارپ

the_king

مدیرکل انجمن
سلامی مجدد
استاد ، میگم پروپرتیِ TransparentControlBitmap ام (درون پنجره ی properties در ویژال استودیو) که در کادرِ جلویی اش ، آدرس کامل فضای نام به همراه نام کلاس را مینویسه (یعنی کد پست 1338 را گذاشتم ، این جوری مینویسه) ، میشه کاریش کرد که خودم هر چی دوست داشتم ، جلوی کادرِ پروپرتیِ TransparentControlBitmap بنویسم ؟ و همچنین کاری کنم که برنامه نویس هر چی دوست داشت بنویسه و من در این صورت ، چیزی که برنامه نویس نوشت را بتونم دریافت کنم؟ (فقط میخوام برنامه نویس بتونه عبارت null را بنویسه). یا اینکه وقتی روی پروپرتی ام کلیک راست کردم ، گزینه ای بنام null هم توی لیستِ کلیک راست اش اضافه بشه و برنامه نویس ، گزینه ی null را انتخاب کرد ، کار خاصی انجام بده؟
همچنین میشه کاری کرد که روی پروپرتی وقتی کلیک راست میکنیم ، گزینه ی ریست فعال باشه و کدی که من میخوام را اجرا کنه؟
اگه آره ، چجوری؟
خیلی ممنون
برای کلاس هاتون ToString رو override کنید.
در ضمن بهتره برای Equals هم روتین مناسب تری override کنید که بر اساس برابری مقادیر مشخصه ها مقایسه کنه، چون بصورت پیشفرض Equals دو شیء با مقادیر کاملا یکسان رو برابر محسوب نمیکنه.

برای مشخصه ها سه تا مورد هست که بهتره رعایت بشه.
مورد اول صفت DefaultValue ئه، اگر مقدار پیشفرض مشخصه رو بشه با DefaultValue وارد کرد، بهتره کنار مشخصه ثبت بشه، مثلا برای مشخصه TabStop نوشته میشه [DefaultValue(true)]. مقدار پیشفرض مشخصه که معلوم باشه Designer میتونه بفهمه مقدار فعلی Reset شدنی هست یا نه. فراموش نکنید که این DefaultValue مستقیما ربطی به مقدار دادن اولیه به مشخصه یا متغیرش نداره و خودکار باعث مقدار دهی مشخصه نمیشه، خودتون باید موقع ساخته شدن شی در متد سازنده اش یا در تعریف متغیرش مقدار اولیه دلخواه تون رو به مشخصه یا متغیر اختصاص بدید که ممکنه حتی مقداری جز این DefaultValue تعیین شده باشه.
مورد دوم متد ResetPropertyName ئه که مقدار مشخصه PropertyName رو ریست می کنه و میتوانید داخلش هر کار دلخواه اضافی هم انجام بدید. Designer ویژوال استدیو از روی اسم متد و مشخصه ارتباط این متد رو با مشخصه تشخیص میده.
مورد سوم متد ShouldSerializePropertyName ئه که اعلام میکنه مقدار مشخصه PropertyName باید ثبت بشه یا نه. معمولا اگر مقدار مشخصه رو کاربر تعیین نکرده باشه، فاقد مقدار باشه یا مقدار پیشفرض باشه، false برگردونده خواهد شد. Designer ویژوال استدیو از روی اسمش ارتباط این متد رو با مشخصه تشخیص میده. مثلا اگر شما برای کنترل مقدار Font رو تعیین نکنید مقدار پیشفرض که از Parent.Font بدست میاد ثبت نمیشه. کنترل فرق میذاره بین Tahoma 8pt ای که شما ثبت می کنید با Tahoma 8pt ای که شما تعیین نکردید و از کنترل Parent به ارث رسیده.

یک متد public void میسازید که اسمش با Reset شروع میشه و اسم مشخصه در ادامه میاد، مثل Control.ResetBackColor که مقدار مشخصه BackColor رو به وضعیت پیشفرض میبره و اصولا با صفت [EditorBrowsable(EditorBrowsableState.Never)] پنهانش میکنید. اون متد Reset تنهایی نمیاد. همراهش یک متد معمولا internal به اسم ShouldSerialize فرضا ShouldSerializeBackColor هم نوشته میشه که مقدار bool برمیگردونه تا Designer بفهمه الان مقدار مشخصه چیزی هست که ارزش ذخیره شدن داشته باشه (و بتونه Reset بشه) یا نه. دیدید در Form1.Designer.cs بعضی از مشخصه ها حتی وقتی null هستند ثبت میشن ولی بقیه در حالت پیشفرض شون مقدار دهی نمیشن؟ دلیلش همون ShouldSerialize ئه که میگه این مشخصه الان مقدار قابل اعتنایی نداره که بخواهیم ثبت بشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
برای کلاس هاتون ToString رو override کنید.
در ضمن بهتره برای Equals هم روتین مناسب تری override کنید که بر اساس برابری مقادیر مشخصه ها مقایسه کنه، چون بصورت پیشفرض Equals دو شیء با مقادیر کاملا یکسان رو برابر محسوب نمیکنه.

برای مشخصه ها سه تا مورد هست که بهتره رعایت بشه.
مورد اول صفت DefaultValue ئه، اگر مقدار پیشفرض مشخصه رو بشه با DefaultValue وارد کرد، بهتره کنار مشخصه ثبت بشه، مثلا برای مشخصه TabStop نوشته میشه [DefaultValue(true)]. مقدار پیشفرض مشخصه که معلوم باشه Designer میتونه بفهمه مقدار فعلی Reset شدنی هست یا نه. فراموش نکنید که این DefaultValue مستقیما ربطی به مقدار دادن اولیه به مشخصه یا متغیرش نداره و خودکار باعث مقدار دهی مشخصه نمیشه، خودتون باید موقع ساخته شدن شی در متد سازنده اش یا در تعریف متغیرش مقدار اولیه دلخواه تون رو به مشخصه یا متغیر اختصاص بدید که ممکنه حتی مقداری جز این DefaultValue تعیین شده باشه.
مورد دوم متد ResetPropertyName ئه که مقدار مشخصه PropertyName رو ریست می کنه و میتوانید داخلش هر کار دلخواه اضافی هم انجام بدید. Designer ویژوال استدیو از روی اسم متد و مشخصه ارتباط این متد رو با مشخصه تشخیص میده.
مورد سوم متد ShouldSerializePropertyName ئه که اعلام میکنه مقدار مشخصه PropertyName باید ثبت بشه یا نه. معمولا اگر مقدار مشخصه رو کاربر تعیین نکرده باشه، فاقد مقدار باشه یا مقدار پیشفرض باشه، false برگردونده خواهد شد. Designer ویژوال استدیو از روی اسمش ارتباط این متد رو با مشخصه تشخیص میده. مثلا اگر شما برای کنترل مقدار Font رو تعیین نکنید مقدار پیشفرض که از Parent.Font بدست میاد ثبت نمیشه. کنترل فرق میذاره بین Tahoma 8pt ای که شما ثبت می کنید با Tahoma 8pt ای که شما تعیین نکردید و از کنترل Parent به ارث رسیده.

یک متد public void میسازید که اسمش با Reset شروع میشه و اسم مشخصه در ادامه میاد، مثل Control.ResetBackColor که مقدار مشخصه BackColor رو به وضعیت پیشفرض میبره و اصولا با صفت [EditorBrowsable(EditorBrowsableState.Never)] پنهانش میکنید. اون متد Reset تنهایی نمیاد. همراهش یک متد معمولا internal به اسم ShouldSerialize فرضا ShouldSerializeBackColor هم نوشته میشه که مقدار bool برمیگردونه تا Designer بفهمه الان مقدار مشخصه چیزی هست که ارزش ذخیره شدن داشته باشه (و بتونه Reset بشه) یا نه. دیدید در Form1.Designer.cs بعضی از مشخصه ها حتی وقتی null هستند ثبت میشن ولی بقیه در حالت پیشفرض شون مقدار دهی نمیشن؟ دلیلش همون ShouldSerialize ئه که میگه این مشخصه الان مقدار قابل اعتنایی نداره که بخواهیم ثبت بشه.

قضیه ی Reset ، خیلی جالب بود . خیلی ممنونم . دست تون درد نکنه. :rose:
اما هنوز متوجه نشدم برای null کردن ، چی کار کنم؟ (نمیخوام وقتی کاربر گزینه ی Reset را زد ، مقدارش null بشه) . مقدار null را میخوام جداگانه یا برنامه نویس بتونه (جلوی کادر اون پروپرتی) بنویسه یا اینکه وقتی روی اون پروپرتی کلیک راست کرد ، گزینه ای اضافه بشه بنام null یا کلا هر روش دیگه ای . مقدار پیش فرض اش هم null نیست و نمیخوام null باشه . پیش فرض اش ، خودش مقدار داره .

بعد اینکه روشی هست که اعضایی که در کلاس پدر ، یعنی کلاس Control تعریف شدن را هم ریست (منظورم به همین منوال ریست شخصی هست) کنیم؟ مثلا عضو Control.Size را ریست کنیم؟ این روش انگار براش جواب نمیده.
 
آخرین ویرایش:

the_king

مدیرکل انجمن
قضیه ی Reset ، خیلی جالب بود . خیلی ممنونم . دست تون درد نکنه. :rose:
اما هنوز متوجه نشدم برای null کردن ، چی کار کنم؟ (نمیخوام وقتی کاربر گزینه ی Reset را زد ، مقدارش null بشه) . مقدار null را میخوام جداگانه یا برنامه نویس بتونه (جلوی کادر اون پروپرتی) بنویسه یا اینکه وقتی روی اون پروپرتی کلیک راست کرد ، گزینه ای اضافه بشه بنام null یا کلا هر روش دیگه ای . مقدار پیش فرض اش هم null نیست و نمیخوام null باشه . پیش فرض اش ، خودش مقدار داره .
در مورد Reset که خودتون در متد ResetPropertyName مشخصه رو مقدار دهی می کنید، هر مقداری، null یا غیر null. مجبور که نیستید به مشخصه مقدار null بدید، متد Reset رو شما می نویسید، اینکه داخلش چکار می کنید که محدود نیست.
گزینه null هم یا حالت انتخاب از بین مقادیر enum ئه که از قبل مشخصه و یکی شون میتونه چیزی مثل None باشه، مثلا Button.DialogResult.
یا برای انتخاب بین مواردی است که یک UITypeEditorEditStyle.DropDown بصورت لیست نشون میده و میتونه یک گزینه اش null یا هر اسم دیگری باشه، مثل Button.Dock.
یا (none) ئه در کنار اشیاء در دسترس در Designer، مثلا ببینید Form.AcceptButton چطور بین همه دکمه های در دسترس و (none) انتخابی انجام میده.
شما می توانید برای مشخصه خودتون یکی از این روش ها رو انتخاب کنید، وگرنه شما در PropertyGrid که شیء سازی نمی کنید که null و new و ... ببینید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
در مورد Reset که خودتون در متد ResetPropertyName مشخصه رو مقدار دهی می کنید، هر مقداری، null یا غیر null. مجبور که نیستید به مشخصه مقدار null بدید، متد Reset رو شما می نویسید، اینکه داخلش چکار می کنید که محدود نیست.
گزینه null هم یا حالت انتخاب از بین مقادیر enum ئه که از قبل مشخصه و یکی شون میتونه چیزی مثل None باشه، مثلا Button.DialogResult.
یا برای انتخاب بین مواردی است که یک UITypeEditorEditStyle.DropDown بصورت لیست نشون میده و میتونه یک گزینه اش null یا هر اسم دیگری باشه، مثل Button.Dock.
یا (none) ئه در کنار اشیاء در دسترس در Designer، مثلا ببینید Form.AcceptButton چطور بین همه دکمه های در دسترس و (none) انتخابی انجام میده.
شما می توانید برای مشخصه خودتون یکی از این روش ها رو انتخاب کنید، وگرنه شما در PropertyGrid که شیء سازی نمی کنید که null و new و ... ببینید.

خیلی ممنون . پس یه گزینه در صفحه ی طراحی برای null کردن اش قرار میدم .
اون تیکه ی آخر که در پست قبل گفتم چی؟:
بعد اینکه روشی هست که اعضایی که در کلاس پدر ، یعنی کلاس Control تعریف شدن را هم ریست (منظورم به همین منوال ریست شخصی هست) کنیم؟ مثلا عضو Control.Size را ریست کنیم؟ این روش انگار براش جواب نمیده.
 

the_king

مدیرکل انجمن
خیلی ممنون . پس یه گزینه در صفحه ی طراحی برای null کردن اش قرار میدم .
اون تیکه ی آخر که در پست قبل گفتم چی؟:
بعد اینکه روشی هست که اعضایی که در کلاس پدر ، یعنی کلاس Control تعریف شدن را هم ریست (منظورم به همین منوال ریست شخصی هست) کنیم؟ مثلا عضو Control.Size را ریست کنیم؟ این روش انگار براش جواب نمیده.
خیلی ساده است.
اگه هدف تون صرفا انتخاب مقدار پیشفرض اختصاصی برای Size ئه که موقع Reset کردن هم بکار میره، باید DefaultSize رو override کنید، مثل سایر کنترل ها :
کد:
protected override Size DefaultSize => new Size(101, 101);
ولی اگه میخواهید در متد Reset کار خاص بیشتری انجام بدید، اول خود Size رو در کنترل تون پیاده سازی کنید :
کد:
        public new Size Size
        {
            get => base.Size;
            set => base.Size = value;
        }

        public void ResetSize()
        {
            Size = new System.Drawing.Size(101, 101);
        }
توجه داشته باشید که Reset رو به تنهایی نمی نویسند چون Designer بدون مشخص شدن مقدار پیشفرض نمیتونه بفهمه کی مقدار پیشفرض ئه و گزینه Reset رو باید disabled کنه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون استاد علی
میگم استاد چجوری هه که توی wpf میشه یه کنترلی را چرخش داد و کلِ کنترل باهاش میچرخه (منظورم فقط رسمِ درون کنترل نیست) اما در winform نمیشه کنترلی را چرخش داد (باز هم منظورم صرفا رسمِ داخل کنترل نیست) ؟ بخاطر اینه که wpf از directx استفاده میکنه هست؟
کلا میشه خودمون یه کدی توی winform بنویسیم که مثل wpf ، کلِ کنترل بچرخه (منظورم صرفا رسمِ داخل کنترل نیست) ؟
نمیدونم تونستم منظورم را برسونم یا نه
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد
استاد ، روشی هست که کد زیر را جوری تغییر بدیم که کار کنه؟ :


کد:
        private void Button1_Click_1(object sender, EventArgs e)
        {
            this.TestRef(ref this.transparentControl1.TransparentControlText.TextFont);
            Font fnt = this.transparentControl1.TransparentControlText.TextFont;
        }

        private void TestRef(ref Font myfonts)
        {
            myfonts = new Font("Cabin Sketch", 20f);
        }

چون در کد بالا ، TextFont که از نوعِ پروپرتی هست را قبول نمیکنه . از طرفی هم نمیخوام از حالتِ پروپرتی خارجش کنم.
شی this.transparentControl1 هم شی ای از کلاس TransparentControl هه.


اگه روشی میشد که باز توی آرایه میریختیم و ارسال میکردیم به تابع TestRef و توی اون تابع اعضای اون آرایه را به شی جدید (در اینجا شی جدید فونت درون تابع TestRef) تغییر میدادیم ، جوری که هر اشاره گری که اعضای اون آرایه ، موقع ارسال بهش اشاره میکرد هم به اون شی جدید اشاره گرش ، تغییرِ اشاره میداد ، خیلی خوب میشد . اما من که روشی برای این قضیه نمیدونم.
 

the_king

مدیرکل انجمن
خیلی ممنون استاد علی
میگم استاد چجوری هه که توی wpf میشه یه کنترلی را چرخش داد و کلِ کنترل باهاش میچرخه (منظورم فقط رسمِ درون کنترل نیست) اما در winform نمیشه کنترلی را چرخش داد (باز هم منظورم صرفا رسمِ داخل کنترل نیست) ؟ بخاطر اینه که wpf از directx استفاده میکنه هست؟

بخاطر DirectX اش نیست، درسته که DirectX در اجرای گرافیکی اش کمک کرده ولی در اصل بخاطر اینه که از ابتدا این قابلیت در طراحی WPF پیشبینی شده. در پنجره های WinForm همچین قابلیتی پیشبینی نشده.


سلامی مجدد
استاد ، روشی هست که کد زیر را جوری تغییر بدیم که کار کنه؟ :


کد:
        private void Button1_Click_1(object sender, EventArgs e)
        {
            this.TestRef(ref this.transparentControl1.TransparentControlText.TextFont);
            Font fnt = this.transparentControl1.TransparentControlText.TextFont;
        }

        private void TestRef(ref Font myfonts)
        {
            myfonts = new Font("Cabin Sketch", 20f);
        }

چون در کد بالا ، TextFont که از نوعِ پروپرتی هست را قبول نمیکنه . از طرفی هم نمیخوام از حالتِ پروپرتی خارجش کنم.
شی this.transparentControl1 هم شی ای از کلاس TransparentControl هه.


اگه روشی میشد که باز توی آرایه میریختیم و ارسال میکردیم به تابع TestRef و توی اون تابع اعضای اون آرایه را به شی جدید (در اینجا شی جدید فونت درون تابع TestRef) تغییر میدادیم ، جوری که هر اشاره گری که اعضای اون آرایه ، موقع ارسال بهش اشاره میکرد هم به اون شی جدید اشاره گرش ، تغییرِ اشاره میداد ، خیلی خوب میشد . اما من که روشی برای این قضیه نمیدونم.
ref برای ارسال شیء ای که هنوز مقدار نداره یا شیء ای که قراره بجایش با new شیء جدیدی ایجاد بشه نیست. از منطق کاری که میکنید سر در نمیارم، ولی اگر بخواهم یک متد آماده new Font("Cabin Sketch", 20f) داشته باشم یا یک متغیر یا مشخصه static رو برای شی اش اختصاص میدم که به هر TextFont ای میشه مقدارش رو نسبت داد یا یک متد Extension برای TransparentControlText میسازم که همچین شیء ای رو برای TextFont ایجاد کنه. یا متد public رو جزئی از TransparentControlText تعریف می کنم که اصلا نیازی به پارامتر ورودی نداشته باشه. یا نهایتا می توانید پارامتر ورودی رو از نوع TransparentControlText در نظر بگیرید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بخاطر DirectX اش نیست، درسته که DirectX در اجرای گرافیکی اش کمک کرده ولی در اصل بخاطر اینه که از ابتدا این قابلیت در طراحی WPF پیشبینی شده. در پنجره های WinForm همچین قابلیتی پیشبینی نشده.

خیلی ممنون استاد علی
خودمون نمیتونیم توی WinForm یه کنترل شخصی تعریف کنیم و کدی بنویسیم که کنترل هاش قابلیت چرخش داشته باشن؟


ref برای ارسال شیء ای که هنوز مقدار نداره یا شیء ای که قراره بجایش با new شیء جدیدی ایجاد بشه نیست. از منطق کاری که میکنید سر در نمیارم، ولی اگر بخواهم یک متد آماده new Font("Cabin Sketch", 20f) داشته باشم یا یک متغیر یا مشخصه static رو برای شی اش اختصاص میدم که به هر TextFont ای میشه مقدارش رو نسبت داد یا یک متد Extension برای TransparentControlText میسازم که همچین شیء ای رو برای TextFont ایجاد کنه. یا متد public رو جزئی از TransparentControlText تعریف می کنم که اصلا نیازی به پارامتر ورودی نداشته باشه. یا نهایتا می توانید پارامتر ورودی رو از نوع TransparentControlText در نظر بگیرید.

خیلی ممنون
دلیل اش اینه که میخوام توی همین قضیه ی ادیتور و کلاس TransparentControlBitmapEditorForm (که در پست 1337 کدش را دادم) ، که کلاسش شکل زیر در میاد :


3.JPG


میخوام برای اون 4 تا دکمه ی Browse Image ، یک رویداد تعریف کنم . ( کار کردش که دیگه مشخص هست . وقتی برنامه نویس ، دکمه ی Browse Image ای را که جلوی لیبلِ Default Bitmap هست را انتخاب کرد (و فایل png ای را انتخاب کرد) ، شی Bitmap جدیدی از اون فایل png ساخته بشه که توی پروپرتی CurrentTransparentControlBitmap.DefaultBitmap (شی CurrentTransparentControlBitmap درون کلاس TransparentControlBitmapEditorForm هست) ریخته بشه . همینطور با کلیک بر دکمه ی Browse Image ای را که جلوی لیبلِ Mouse Enter Bitmap هست ، شی Bitmap جدیدی از اون فایل png ساخته بشه که توی پروپرتی CurrentTransparentControlBitmap.MouseEnterBitmap ریخته بشه و همین روند برای بقیه ی دکمه های Browse Image هست ) .

بنابراین میخوام با روشی کد بنویسیم که هر بار شرط و if های مداوم ننویسم . (هر چند راهکار آخرش انگار همین if نوشتن هست و به ظاهر انگار چاره ی دیگه ای نیست) .
برای این کار ، یه راهکار به ذهنم اومد که برای دکمه ی Browse Image مربوط به Default Bitmap ، مقدار Tag برای این دکمه را 0 ؛ و مقدار Tag برای دکمه ی Browse Image مربوط به Mouse Enter Bitmap را 1 بگیریم و همین روند را ادامه بدم.
بعد اعضای CurrentTransparentControlBitmap.DefaultBitmap و CurrentTransparentControlBitmap.MouseEnterBitmap و CurrentTransparentControlBitmap.MouseDownBitmap و CurrentTransparentControlBitmap.ControlDisabledBitmap را به ترتیب توی یه آرایه بریزم. و بصورت ref ، این آرایه را به متدی بفرستم.
بعد توی این متد ، عضوِ Tag مربوط به اون دکمه ی Browse Image را به عنوانِ اندیسِ این آرایه ، شی جدیدی از بیت مپ براش بسازم (جوری که اشاره گرِ اون آرایه که به شی جدید تغییر کرد ، اشاره گرِ این ها مثلا اشاره گرِ CurrentTransparentControlBitmap.DefaultBitmap را هم اتوماتیک تغییر بده) که این طور نمیشه (که دلیلش میدونم) .


یا اینکه آرایه را به اون متد نفرستم و فقط بیت مپ های CurrentTransparentControlBitmap.DefaultBitmap و CurrentTransparentControlBitmap.MouseEnterBitmap و CurrentTransparentControlBitmap.MouseDownBitmap و CurrentTransparentControlBitmap.ControlDisabledBitmap را بصورت اعضای جداگانه بفرستم که باز هم در این صورت هم اینکه نمیشه (چون میگه عضو DefaultBitmap اش نباید پروپرتی باشه و من هم نمیخوام به حالت فیلد درش بیارم و هم اینکه شدنی هم بشه ، باز هم این روش دوم ، لازم داره براش شرط if بذارم)

حالا من که به ذهنم نمیرسه جوری کدش را بنویسم که شرط لازم نباشه بنویسم . شما میدونید؟

خیلی ممنون .

این ها چیه خودش نوشته میشه گاها؟!!
 

the_king

مدیرکل انجمن
خیلی ممنون استاد علی
خودمون نمیتونیم توی WinForm یه کنترل شخصی تعریف کنیم و کدی بنویسیم که کنترل هاش قابلیت چرخش داشته باشن؟
قطعا میتونیم ولی برای طراحی بستر اش وقت زیادی صرف خواهد شد، نهایتا میشه یک پلتفرم ویژوال جدید، مثل Adobe Flash یا WPF. نمی توانید کنترل تون رو در بستری پیاده سازی کنید که مهیا نیست. باید بجای سیستم کنترل های پنجره ای استاندارد پلتفرم خاص خودتون رو طراحی می کنید. کنترلی که قابلیت چرخش داره روی چی رسم بشه؟ روی پنجره های ویندوز که قابلیت چرخش نداره؟ بدیهیه که نمیتوانید با پنجره ای که ابعادش 80x25 پیکسل ئه، کنترل 80x25 رو 90 درجه دوران بدید چون داخل فضاش جا نمیشه.

بنابراین میخوام با روشی کد بنویسیم که هر بار شرط و if های مداوم ننویسم . (هر چند راهکار آخرش انگار همین if نوشتن هست و به ظاهر انگار چاره ی دیگه ای نیست) .
این ها چیه خودش نوشته میشه گاها؟!!
برای چی اصرار دارید از ابتدا تا انتها متن رو Bold بنویسید؟
می توانید با Systsem.Reflection از if فرار کنید ولی معمولا تلاش بیش از حد برای خلاصه سازی به کاهش کارایی منجر میشه. در کد نویسی شما باید به این فکر کنید که چطور بار پردازش کنترل رو کم کنید، سرعت اجراشو افزایش بدید، موارد اضافی رو حذف کنید، کاربری شو ساده تر کنید. اینکه if کمتری بنویسید به خودی خود ارزشی نداره. وقتی ارزش پیدا می کنه که یا از روتین تکراری قابل توجهی فاکتور گرفته باشید یا در کارایی تاثیر محسوسی بذاره.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد استاد.
bold را بخاطر این انجام میدم چون کلمات درشت میشه و راحت تر میبینم . شما هم بولد کنین ، من راحت ترم :green:
استاد ، میگم من فایل ها را در گفتگوی خصوصی براتون فرستادم .
وقتی در صفحه ای که برای پنجره ی Properties طراحی کردم ، میرم (یعنی از درون پنجره ی Properties میرم و پروپرتیِ TransparentControlBitmap را انتخاب میکنم و صفحه ای که طراحی کردم باز میشه) و دکمه ی Browse Image ای که مربوط به DefaultBitmap هست را میزنم و یه فایل png انتخاب میکنم ، همه چیز درست انجام میشه و در صفحه ی طراحی (و حتی در شی transparentControl ای که روی فرمِ هم قرار داره) ، مقدارِ DefaultBitmap اش تغییر میکنه . اما وقتی پروژه را اجرا میکنم ، فقط زمان اجرا ، این تغییرات اِعمال نمیشه و فقط متد سازنده ی پیش فرض اش انگار از اول اجرا میشه و کلا هر کاری که توی متد سازنده ی پیش فرض انجام دادم ، اِعمال میشه .
و دوم اینکه وقتی ، تغییرات را اِعمال کردم و ویژال استودیو را بستم ، و دوباره ویژال استودیو را باز کنم ، از روی فرمِ طراحی هم ریست میشه و تغییراتی که اِعمال کرده بودم ، نادیده گرفته میشه و انگار فقط متد سازنده اش اجرا میشه. برای این قضیه ی دوم ، اطلاعات را باید توی دیتابیس مگه ثبت کنم؟

مشکل دو قضیه از کجاست؟
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلامی مجدد استاد.
bold را بخاطر این انجام میدم چون کلمات درشت میشه و راحت تر میبینم . شما هم بولد کنین ، من راحت ترم :green:
استاد ، میگم من فایل ها را در گفتگوی خصوصی براتون فرستادم .
وقتی در صفحه ای که برای پنجره ی Properties طراحی کردم ، میرم (یعنی از درون پنجره ی Properties میرم و پروپرتیِ TransparentControlBitmap را انتخاب میکنم و صفحه ای که طراحی کردم باز میشه) و دکمه ی Browse Image ای که مربوط به DefaultBitmap هست را میزنم و یه فایل png انتخاب میکنم ، همه چیز درست انجام میشه و در صفحه ی طراحی (و حتی در شی transparentControl ای که روی فرمِ هم قرار داره) ، مقدارِ DefaultBitmap اش تغییر میکنه . اما وقتی پروژه را اجرا میکنم ، فقط زمان اجرا ، این تغییرات اِعمال نمیشه و فقط متد سازنده ی پیش فرض اش انگار از اول اجرا میشه و کلا هر کاری که توی متد سازنده ی پیش فرض انجام دادم ، اِعمال میشه .
و دوم اینکه وقتی ، تغییرات را اِعمال کردم و ویژال استودیو را بستم ، و دوباره ویژال استودیو را باز کنم ، از روی فرمِ طراحی هم ریست میشه و تغییراتی که اِعمال کرده بودم ، نادیده گرفته میشه و انگار فقط متد سازنده اش اجرا میشه. برای این قضیه ی دوم ، اطلاعات را باید توی دیتابیس مگه ثبت کنم؟

مشکل دو قضیه از کجاست؟
عامل دو تا قضیه یک مورد ئه، دو مورد مجزا نیستند. موقع اجرا کردن برنامه چی اجرا میشه؟ کدی که هست، هیچ مورد اضافی خارج از کدی که اجرا نمیشه. در کد Form1.Designer.cs کنترل با متد سازنده ایجاد میشه و بعد مشخصه ها در ادامه مقدار دهی میشن. از جایی خارج از این کد ها مقدار دهی تزریق نمیشه.
وقتی شما یک کنترل فرضا از نوع Button رو روی فرم قرار میدهید، Designer ابتدا با کد سازی یک متغیر برایش میسازه، بعد با کد سازی با متد سازنده بدون پارامتر ایجادش می کنه، و بعد با کد سازی مشخصه هاشو مقدار دهی می کنه و نهایتا با کد سازی به فرم اضافه اش می کنه. در هنگام طراحی فرم هم کنترل رو زیر نظر داره و چه مشخصه هاش تغییر کرد و چه والدش تغییر کرد، تغییرات رو در کدی که نوشته اعمال می کنه. برای همین موقع اجرای برنامه اون تغییراتی که در مشخصه یک کنترل دادید بخاطر سپرده شده، دیتابیس در واقع همون کد Form1.Designer.cs ئه. قبلا هم گفتم که Designer صرفا میتونه از متد سازنده بدون پارامتر استفاده کنه.

حالا بریم سراغ شرایط کنترل شما، شما برای کنترل تون یک TransparentControlBitmap میسازید، چیزی که Designer نمیتونه انجام بده، چون هیچ شناختی از پارامتر های سازنده اش نداره، ارتباط بین مشخصه ها و سازنده اش رو هم که درک نمی کنه، Designer هوشمندی انسان رو نداره، هیچ معیاری برای انتخاب متد سازنده با پارامتر نداره. همانطور که ارتباط بین مشخصه ها و پارامتر های سازنده کنترل تون رو درک نمی کنه و نمیتونه کنترل تون رو بسازه. برای همین هم دخالتی در مقدار دهی مشخصه TransparentControlBitmap کنترل تون نداره. شما در موقع اجرای برنامه تون همون کدی رو اجرا می کنید که در Form1.Designer.cs دستی نوشته بودید یا Designer توانسته بود مقدار دهی کنه، بخشی که از تغییرات رو که نه شما دستی نوشتید و نه Designer تونسته کدش رو بنویسه نادیده گرفته میشه.
وقتی کلاس توسط Designer ایجاد شدنی نباشه، نمیتونه مسئولیت بازتولید کد مقدار دهی مشخصه هاش رو داشته باشه چون اول باید بتونه شیء اش رو بسازه. یعنی شما عملا از کد نویس میخواهید ساختن شیء از TransparentControlBitmap و مقدار دهی مشخصه ها رو هم خودش انجام بده، همانطور که ساختن کنترل رو خودش انجام داده بود. قبلا هم بهتون گفتم، برنامه نویس نباید در بخش Designer فرم کدی بنویسه، اون بخش مربوط به Designer ئه، مربوط به برنامه نویس نیست. خلاف جهت جریان آب شنا می کنید. کنترل شما و کلاس های جانبی تون روال استاندارد مناسب Designer رو طی نمی کنه، برای همینه که از کمک Designer برخوردار نیست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
عامل دو تا قضیه یک مورد ئه، دو مورد مجزا نیستند. موقع اجرا کردن برنامه چی اجرا میشه؟ کدی که هست، هیچ مورد اضافی خارج از کدی که اجرا نمیشه. در کد Form1.Designer.cs کنترل با متد سازنده ایجاد میشه و بعد مشخصه ها در ادامه مقدار دهی میشن. از جایی خارج از این کد ها مقدار دهی تزریق نمیشه.
وقتی شما یک کنترل فرضا از نوع Button رو روی فرم قرار میدهید، Designer ابتدا با کد سازی یک متغیر برایش میسازه، بعد با کد سازی با متد سازنده بدون پارامتر ایجادش می کنه، و بعد با کد سازی مشخصه هاشو مقدار دهی می کنه و نهایتا با کد سازی به فرم اضافه اش می کنه. در هنگام طراحی فرم هم کنترل رو زیر نظر داره و چه مشخصه هاش تغییر کرد و چه والدش تغییر کرد، تغییرات رو در کدی که نوشته اعمال می کنه. برای همین موقع اجرای برنامه اون تغییراتی که در مشخصه یک کنترل دادید بخاطر سپرده شده، دیتابیس در واقع همون کد Form1.Designer.cs ئه. قبلا هم گفتم که Designer صرفا میتونه از متد سازنده بدون پارامتر استفاده کنه.

خیلی ممنون استاد.

حالا بریم سراغ شرایط کنترل شما، شما برای کنترل تون یک TransparentControlBitmap میسازید، چیزی که Designer نمیتونه انجام بده، چون هیچ شناختی از پارامتر های سازنده اش نداره، ارتباط بین مشخصه ها و سازنده اش رو هم که درک نمی کنه، Designer هوشمندی انسان رو نداره، هیچ معیاری برای انتخاب متد سازنده با پارامتر نداره. همانطور که ارتباط بین مشخصه ها و پارامتر های سازنده کنترل تون رو درک نمی کنه و نمیتونه کنترل تون رو بسازه. برای همین هم دخالتی در مقدار دهی مشخصه TransparentControlBitmap کنترل تون نداره.

خیلی ممنون استاد. :rose:
نقل قول هایی ازتون که رنگی کردم را نگاه میندازین استاد؟
من از این گفته هاتون حس میکنم که این رو میگین که اصلا کنترل TransparentControl ام را دیزاینر ویژال استودیو نمیتونه ایجاد کنه و فقط توسط کدنویسی ، توسط برنامه نویس باید ایجادش کرد . منظور شما همینه؟
اگه اینه ، همونطور که میبینید ، هم برای کلاس TransparentControl و هم برای کلاس TransparentControlBitmap و هم برای کلاس TransparentControlText ، متد سازنده ی پیش فرض (بدون پارامتر) ساختم و دیزاینر ویژال استودیو میتونه موقع طراحی ، به فرم یا کنترلِ مورد نظرمون اضافه اش کنه.

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

لازم به انتخاب متد سازنده ی غیر پیش فرض نیست . من برای اون کلاس ها متد سازنده ی پیش فرض هم تعریف کردم.
یادآوری کنم که من آخرین فایل ها را در گفتگوی خصوصی براتون آپلود کردم. نمیدونم اون فایل ها را دیدین یا فایل هایی که در گذشته و در پست های قبل دیدین را مد نظرتون دارین.

شما در موقع اجرای برنامه تون همون کدی رو اجرا می کنید که در Form1.Designer.cs دستی نوشته بودید یا Designer توانسته بود مقدار دهی کنه، بخشی که از تغییرات رو که نه شما دستی نوشتید و نه Designer تونسته کدش رو بنویسه نادیده گرفته میشه.

من در دیزاینر که کد را میبینم (در فایل Form1.Designer.cs منظورمه) ، چه قبل از تغییراتی که در پست قبل گفتم و چه بعد از اِعمال تغییراتی که در پست قبل گفتم را بدم (تغییر پروپرتیِ TransparentControlBitmap.DefaultBitmap) در هر صورت ، فقط کد زیر در دیزاینر نوشته میشه :

کد:
transparentControlBitmap1.DefaultBitmap = ((System.Drawing.Bitmap)(resources.GetObject("transparentControlBitmap1.DefaultBitmap")));

چرا؟
اما همونطور که در پست قبل گفتم ، موقع طراحی ، توی فرم ، اون تغییرات دیده میشه اما موقعی که برنامه را اجرا میکنم (یا ویژال استودیو را میبندم و دوباره باز میکنم) ، اون تغییرات اِعمال نمیشه.
فکر کنم فقط واسه همینه که این کد بالا ، تغییری نمیکنه . اصلا این کد بالا چیه؟ یعنی شیِ resources ، چیه؟ به طَبَعِ اون ، متد GetObject اش چیه؟ من که همچین کدی ننوشته بودم. نوشتم اگه فایل png انتخاب شد ، یه شی جدید Bitmap از مهون آدرس فایل png برای اون بسازه.
کلا من حدس میزنم به احتمال بسیار زیاد ، مشکل از این خط باشه.
چجوری میشه این خط را اصلاح کرد؟

کلا شیِ TransparentControl ام در دیزاینر ، به شکل زیر مقداردهی شد :

کد:
            this.transparentControl1 = new CustomControl.Transparent.TransparentControl();


            this.transparentControl1.AutoCalculateForeBackgroundControls = true;
            this.transparentControl1.BackgroundControls = null;
            this.transparentControl1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
            this.transparentControl1.ForegroundControls = null;
            this.transparentControl1.GraphicCompositingQuality = System.Drawing.Drawing2D.CompositingQuality.Invalid;
            this.transparentControl1.GraphicPixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Invalid;
            this.transparentControl1.Location = new System.Drawing.Point(535, 22);
            this.transparentControl1.Name = "transparentControl1";
            this.transparentControl1.Size = new System.Drawing.Size(90, 35);
            this.transparentControl1.TabIndex = 0;
            this.transparentControl1.TabStop = false;
            this.transparentControl1.TextAutoSize = false;
            transparentControlBitmap1.Bounds = new System.Drawing.Rectangle(0, 0, 90, 35);
            transparentControlBitmap1.ControlDisabledBitmap = ((System.Drawing.Bitmap)(resources.GetObject("transparentControlBitmap1.ControlDisabledBitmap")));
            transparentControlBitmap1.DefaultBitmap = ((System.Drawing.Bitmap)(resources.GetObject("transparentControlBitmap1.DefaultBitmap")));
            transparentControlBitmap1.GraphicInterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Invalid;
            transparentControlBitmap1.Location = new System.Drawing.Point(0, 0);
            transparentControlBitmap1.MouseDownBitmap = ((System.Drawing.Bitmap)(resources.GetObject("transparentControlBitmap1.MouseDownBitmap")));
            transparentControlBitmap1.MouseEnterBitmap = ((System.Drawing.Bitmap)(resources.GetObject("transparentControlBitmap1.MouseEnterBitmap")));
            transparentControlBitmap1.Size = new System.Drawing.Size(90, 35);
            transparentControlBitmap1.TransparentControl = this.transparentControl1;
            this.transparentControl1.TransparentControlBitmap = transparentControlBitmap1;
            transparentControlText1.GraphicSmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Invalid;
            transparentControlText1.GraphicTextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault;
            transparentControlText1.Text = "شفاف";
            transparentControlText1.TextBound = ((System.Drawing.RectangleF)(resources.GetObject("transparentControlText1.TextBound")));
            transparentControlText1.TextFont = new System.Drawing.Font("Arial", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(178)));
            transparentControlText1.TextForeColor = System.Drawing.SystemColors.ControlText;
            transparentControlText1.TextLocation = ((System.Drawing.PointF)(resources.GetObject("transparentControlText1.TextLocation")));
            transparentControlText1.TextRightToLeft = System.Windows.Forms.RightToLeft.No;
            transparentControlText1.TextSize = new System.Drawing.SizeF(41.77588F, 24.22314F);
            transparentControlText1.TextStringFormat = null;
            transparentControlText1.TransparentControl = this.transparentControl1;
            this.transparentControl1.TransparentControlText = transparentControlText1;

فکر کنم جاهایی که از resources.GetObject برای مقداردهی استفاده کرده ، به مشکل بخورم.
چجوری میشه کاری کرد که دیزاینر ، کد resources.GetObject را ننویسه؟

وقتی کلاس توسط Designer ایجاد شدنی نباشه، نمیتونه مسئولیت بازتولید کد مقدار دهی مشخصه هاش رو داشته باشه چون اول باید بتونه شیء اش رو بسازه. یعنی شما عملا از کد نویس میخواهید ساختن شیء از TransparentControlBitmap و مقدار دهی مشخصه ها رو هم خودش انجام بده، همانطور که ساختن کنترل رو خودش انجام داده بود. قبلا هم بهتون گفتم، برنامه نویس نباید در بخش Designer فرم کدی بنویسه، اون بخش مربوط به Designer ئه، مربوط به برنامه نویس نیست. خلاف جهت جریان آب شنا می کنید. کنترل شما و کلاس های جانبی تون روال استاندارد مناسب Designer رو طی نمی کنه، برای همینه که از کمک Designer برخوردار نیست.

کلاسم متد سازنده ی پیش فرض داره و توسط دیزاینر ، موقع طراحی ، ایجاد میشه.

خیلی ممنون استاد.
 

the_king

مدیرکل انجمن
خیلی ممنون استاد.
خیلی ممنون استاد. :rose:
نقل قول هایی ازتون که رنگی کردم را نگاه میندازین استاد؟
من از این گفته هاتون حس میکنم که این رو میگین که اصلا کنترل TransparentControl ام را دیزاینر ویژال استودیو نمیتونه ایجاد کنه و فقط توسط کدنویسی ، توسط برنامه نویس باید ایجادش کرد . منظور شما همینه؟
اگه اینه ، همونطور که میبینید ، هم برای کلاس TransparentControl و هم برای کلاس TransparentControlBitmap و هم برای کلاس TransparentControlText ، متد سازنده ی پیش فرض (بدون پارامتر) ساختم و دیزاینر ویژال استودیو میتونه موقع طراحی ، به فرم یا کنترلِ مورد نظرمون اضافه اش کنه.

منظورتون از شناخت پارامترهای متد سازنده توسط دیزاینر و اینکه دیزاینر باید رابطه ی بین پروپرتی ها و سازنده اش را بدونه را هم متوجه نشدم .
خوب دیزاینر چه کار به ارتباطش داره؟ اصلا معنای ارتباط یه چیز با یه چیز دیگه ، توسط دیزاینر ، چجوری درک میشه؟ دیزاینر فقط کد را میخواد اجرا کنه دیگه . چه کار به رابطه ی بین کدها داره؟
کلا رابطه اگه چجوری باشه ، دیزاینر مشکلی نداره؟
Designer قراره فقط کد رو اجرا کنه؟ پس کد نویسی داخل Form1.Designer.cs رو کی انجام داده؟ اگر Designer قراره فقط کد رو اجرا کنه، پس لطفا برای کنترل تون یک بخش ذخیره سازی اطلاعات در فایل هم بسازید و یک بخش خواندن اطلاعات از فایل و یک کد رو هم به برنامه نویس اعلام کنید که اول برنامه اش فلان سطر کد رو اجرا کنه تا اطلاعات از فایل خونده بشه و ...
اما این روال در سایر کنترل های ویژوال نیست، وقتی شما در هنگام طراحی فرم، در یک مشخصه شیء ای رو قرار می دهید، Designer باید هم قادر به ذخیره کردن مقدار شیء باشه و هم بازتولید اون شی.
Designer هم نه کدی که شما داخل Form1.Designer.cs می نویسید رو میتونه تفسیر کنه و نه میتونه بفهمه پارامتر های متد سازنده چه معنی و کاربردی دارند و نه میفهمه این مشخصه که سعی میکنه ذخیره اش کنه چه تاثیری در شیء داره.
فرض کنید یک کلاس داریم با متد سازنده (int x) و دو مشخصه string a و string b. شما از روی شیء m که از نوع همین کلاس بوده میتوانید بفهمید x چه مقداری داشته؟ نه. از ارتباط x و a و b چیزی متوجه میشید؟ نه. آیا منطقی هست که فرض کنیم اگر بخواهیم m رو در فایل ذخیره کنیم و بعدا دوباره بخونیم، با ثبت مقدار مشخصه های a و b میشه شیء مشابه رو باز تولید کرد؟ نه. Designer به همین میزان از کلاس ها و اشیاء شما و هر شخص دیگری سردر میاره. نه میفهمه پارامتر ها چه کارکردی دارند و نه مشخصه ها. فقط هم چشم بسته مقادیری رو میخونه و بازیابی میکنه، بدون اینکه بفهمه آیا اینکار منجر به بازتولید همون شیء میشه یا نه. اگر Designer نتوانست شیء رو بازتولید کنه مقصر Designer نیست، طراح کلاس ئه که باید روشی ارائه کنه که بشه ثبت اش کرد، مثلا اگر Designer ببینه کلاس بصورت دو طرفه به string قابل تبدیل ئه، مشکلی برای ثبت کردنش نداره، حتی اگه مشخصه ای نداشته باشه، اما فرضا کلاسی که متد سازنده اش رو نمیشناسه، یا مشخصه هایش فقط خواندنی هستند و به داده مناسب دیگری هم قابل تبدیل نیست و روشی هم برای serialization ارائه نکرده رو چطوری در Form1.Designer.cs باز تولید کنه؟

یک مثال مناسب Font ئه، Font در پیاده سازی اش اولا ISerializable رو پیاده سازی کرده، یعنی اگر لازم باشه جایی ذخیره بشه، Designer سردرگم نمیشه که بین اینهمه مشخصه readonly چیکار کنم و بیخودی مشخصه های بدرنخور مثل FontFamily رو ثبت نمی کنه. از طرف دیگه Editor اش رو ابتدای خود کلاس تعریف کرده تا مشخص باشه Font ها چطور ویرایش بشن. در ضمن TypeConverter مناسب داره که هم میتونه دو طرفه به string تبدیلش کنه و هم به InstanceDescriptor تبدیلش کنه. InstanceDescriptor میگه اگر میخواهی برای این شیء Font که در مشخصه ای هست یک متد سازنده کد نویسی کنی، متد سازنده فلان رو انتخاب کن با مقدار پارامتر های فلان و بهمان. برای همینه که مبینید Designer میتونه با new Font خیلی راحت کار کنه.
اون InstanceDescriptor دقیقا همون چیزی است که به Designer میفهمونه اگر خواست این شیء m رو ایجاد کنه باید چه مقداری رو به پارامتری x بده.

لازم به انتخاب متد سازنده ی غیر پیش فرض نیست . من برای اون کلاس ها متد سازنده ی پیش فرض هم تعریف کردم.
یادآوری کنم که من آخرین فایل ها را در گفتگوی خصوصی براتون آپلود کردم. نمیدونم اون فایل ها را دیدین یا فایل هایی که در گذشته و در پست های قبل دیدین را مد نظرتون دارین.
فایلی که با پیام خصوصی ارسال کردید رو بررسی نکردم و نمی کنم. قبلا هم بهتون گفتم که پیام خصوصی رو برای موارد مربوط به سوالات برنامه نویسی بکار نمی برم.
اینکه کلاس هاتون متد سازنده بدون پارامتر داشته باشند قدم بزرگیه، چون حداقل کارکرد اش اینه که Designer میتونه ایجاد شون کنه.
توقع دارید بجای resources.GetObject تصویر Bitmap با چه کدی ایجاد بشه؟ وقتی شما در یک مشخصه تصویر Bitmap ای قرار میدهید که Designer نمیاد یک کد برای خواندن فایل تصویر png از درایو فلان بنویسه، اصلا از روی Bitmap نمیفهمه منبع اش چی بوده، فایل png بوده، از طریق یک stream ایجاد شده یا خودتون با Graphics طراحی اش کردید و ....
Bitmap به هر شیوه ای که ایجاد شده باشه باید بصورت داده باینری ذخیره بشه، نه اینکه با خواندن فایل png از مسیر فلان مجددا ایجاد بشه.
resources.GetObject مشکلی ایجاد نمی کنه چون روال استانداردی است برای ذخیره کردن داده هایی مثل اون Bitmap که برای serialization شون روش تخصصی دیگری طراحی نشده که Designer بخواد ازش استفاده کنه.
همون Bitmap ای که ذخیره کرده رو عینا برمیگردونه. اگر داده تصویر عوض بشه صرفا محتویات در Resources تغییر میکنه، نه اون کد داخل Designer، چون نه اسم مشخصه عوض شده و نه اسم کنترل که کد تغییر کنه.
در نظر بگیرید که DefaultBitmap از نوع Bitmap ئه، نه string. مسیر فایل png رو که ذخیره نمی کنه، داده تصویر رو ذخیره می کنه. بعد از مقدار دهی Bitmap به DefaultBitmap نه کنترل تون و نه Designer نخواهد فهمید که مسیر فایل png کجا بود، نتیجه عملیات ساختن یک Bitmap بوده که حالا باید داده اش ذخیره بشه. به همین جهت برای نگهداری مقدار TransparentControlBitmap و بصورت جزئی تر مشخصه ای مثل DefaultBitmap باید اون Bitmap در جایی که قابلیت ثبت داده های باینری رو داره ذخیره بشه. اینجور اشیاء که داده باینری دارن بصورت Resource ذخیره میشن، همانطور که تصاویر سایر کنترل ها هم بصورت Resource عمومی یا محلی ذخیره میشن. موقعی که شما تصویری رو با Editor ای که خودتون ساختید در مشخصه قرار می دهید، کد Editor در حال اجرا شدنه و اینکه تصویر در کنترل نمایش داده میشه نشون میده که Editor کارش رو انجام داده.
اگر ذخیره شدن انجام نشده باشه، چیزی که مانع ذخیره شدن مقدار مشخصه شده کدی در ادامه است که با خطا ادامه روتین رو متوقف میکنه، پس در روتین هایی که دارید دنبال خطای نهفته بگردید.
اما اگر ذخیره سازی درست انجام میشه ولی بعد از فراخوانی تصویر در ادامه روالی طی میشه که نمایش به درستی صورت نمیگیره، باید مرحله به مرحله مقدار مشخصه رو بررسی کنید تا بببینید در کجا از دست میره.
پیشنهاد می کنم قبل از اینکه یک روال جدید و ناآشنا رو روی کنترل تون امتحان کنید اول روی یک مثال کوچک در کلاس دیگری امتحانش کنید تا به نتیجه برسید و پیدا کردن دلیل خطاها ساده تر باشه. وگرنه هر چقدر حجم کد بالاتر بره پیدا کردن خطا در کنترل تون سخت تر میشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یک مثال مناسب Font ئه، Font در پیاده سازی اش اولا ISerializable رو پیاده سازی کرده، یعنی اگر لازم باشه جایی ذخیره بشه، Designer سردرگم نمیشه که بین اینهمه مشخصه readonly چیکار کنم و بیخودی مشخصه های بدرنخور مثل FontFamily رو ثبت نمی کنه. از طرف دیگه Editor اش رو ابتدای خود کلاس تعریف کرده تا مشخص باشه Font ها چطور ویرایش بشن. در ضمن TypeConverter مناسب داره که هم میتونه دو طرفه به string تبدیلش کنه و هم به InstanceDescriptor تبدیلش کنه. InstanceDescriptor میگه اگر میخواهی برای این شیء Font که در مشخصه ای هست یک متد سازنده کد نویسی کنی، متد سازنده فلان رو انتخاب کن با مقدار پارامتر های فلان و بهمان. برای همینه که مبینید Designer میتونه با new Font خیلی راحت کار کنه.
اون InstanceDescriptor دقیقا همون چیزی است که به Designer میفهمونه اگر خواست این شیء m رو ایجاد کنه باید چه مقداری رو به پارامتری x بده.

خیلی ممنون استاد از توضیح مفصل تون.
خوب منم همین رو میگم . مثالش Font هست . خیلی از کنترل هایی که شرکت های دیگه هم میزنن ، هست و ... .
شما همیشه میگین چرا دو تا کلاس مجزای دیگه زدم.
یه چیزهایی متوجه شدم . اما دقیقا متوجه نشدم باید چی کار کنم؟ روی چه کلاس و چه پروپرتی ای ، چه اتریباتس (یا اتریباتس هایی) و چه کارهای اضافه تری باید انجام بدم؟
این EditorAttributes را الان بجای اینکه روی پروپرتی TransparentControl.TransparentControlBitmap قرار بدم ، باید روی کلاس TransparentControl قرار بدم؟
کلا یه کم بیشتر راهنمایی کنین.

فایلی که با پیام خصوصی ارسال کردید رو بررسی نکردم و نمی کنم. قبلا هم بهتون گفتم که پیام خصوصی رو برای موارد مربوط به سوالات برنامه نویسی بکار نمی برم.

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

اینکه کلاس هاتون متد سازنده بدون پارامتر داشته باشند قدم بزرگیه، چون حداقل کارکرد اش اینه که Designer میتونه ایجاد شون کنه.
توقع دارید بجای resources.GetObject تصویر Bitmap با چه کدی ایجاد بشه؟ وقتی شما در یک مشخصه تصویر Bitmap ای قرار میدهید که Designer نمیاد یک کد برای خواندن فایل تصویر png از درایو فلان بنویسه، اصلا از روی Bitmap نمیفهمه منبع اش چی بوده، فایل png بوده، از طریق یک stream ایجاد شده یا خودتون با Graphics طراحی اش کردید و ....
Bitmap به هر شیوه ای که ایجاد شده باشه باید بصورت داده باینری ذخیره بشه، نه اینکه با خواندن فایل png از مسیر فلان مجددا ایجاد بشه.
resources.GetObject مشکلی ایجاد نمی کنه چون روال استانداردی است برای ذخیره کردن داده هایی مثل اون Bitmap که برای serialization شون روش تخصصی دیگری طراحی نشده که Designer بخواد ازش استفاده کنه.
همون Bitmap ای که ذخیره کرده رو عینا برمیگردونه. اگر داده تصویر عوض بشه صرفا محتویات در Resources تغییر میکنه، نه اون کد داخل Designer، چون نه اسم مشخصه عوض شده و نه اسم کنترل که کد تغییر کنه.
در نظر بگیرید که DefaultBitmap از نوع Bitmap ئه، نه string. مسیر فایل png رو که ذخیره نمی کنه، داده تصویر رو ذخیره می کنه. بعد از مقدار دهی Bitmap به DefaultBitmap نه کنترل تون و نه Designer نخواهد فهمید که مسیر فایل png کجا بود، نتیجه عملیات ساختن یک Bitmap بوده که حالا باید داده اش ذخیره بشه. به همین جهت برای نگهداری مقدار TransparentControlBitmap و بصورت جزئی تر مشخصه ای مثل DefaultBitmap باید اون Bitmap در جایی که قابلیت ثبت داده های باینری رو داره ذخیره بشه. اینجور اشیاء که داده باینری دارن بصورت Resource ذخیره میشن، همانطور که تصاویر سایر کنترل ها هم بصورت Resource عمومی یا محلی ذخیره میشن. موقعی که شما تصویری رو با Editor ای که خودتون ساختید در مشخصه قرار می دهید، کد Editor در حال اجرا شدنه و اینکه تصویر در کنترل نمایش داده میشه نشون میده که Editor کارش رو انجام داده.
اگر ذخیره شدن انجام نشده باشه، چیزی که مانع ذخیره شدن مقدار مشخصه شده کدی در ادامه است که با خطا ادامه روتین رو متوقف میکنه، پس در روتین هایی که دارید دنبال خطای نهفته بگردید.
اما اگر ذخیره سازی درست انجام میشه ولی بعد از فراخوانی تصویر در ادامه روالی طی میشه که نمایش به درستی صورت نمیگیره، باید مرحله به مرحله مقدار مشخصه رو بررسی کنید تا بببینید در کجا از دست میره.
پیشنهاد می کنم قبل از اینکه یک روال جدید و ناآشنا رو روی کنترل تون امتحان کنید اول روی یک مثال کوچک در کلاس دیگری امتحانش کنید تا به نتیجه برسید و پیدا کردن دلیل خطاها ساده تر باشه. وگرنه هر چقدر حجم کد بالاتر بره پیدا کردن خطا در کنترل تون سخت تر میشه.

توقع داشتم همون کدی که من نوشتم را بنویسه دیگه .
یعنی TransparentControlBitmap.DefaultBitmap = new Bitmap("file address") را بذاره.
به هر حال . پس الان مشکل از resources.GetObject نیست . در اونجا ، مقدار اون فایل تصویر ، بصورت باینری ذخیره میشه و خونده میشه. (توی فایل Resources.resx ذخیره میشه؟)
من الان چه کدی را باید چک کنم؟ کلا اون قسمت از کد Editor ام که باعث میشه بیت مپی جدید را اختصاص بده ، 2 خط بیشتر نیست :

کد:
if (btnBrowseImage.Equals(this.btnBrowseDefaultBitmap) == true)
            {
                this.CurrentTransparentControlBitmap.DefaultBitmap = new Bitmap(this.browseFileDialog.FileName);
                this.transparentDefaultBitmap.TransparentControlBitmap.DefaultBitmap = this.CurrentTransparentControlBitmap.DefaultBitmap;
            }

CurrentTransparentControlBitmap هم شی جاری و برابر با پروپرتیِ TransparentControl.TransparentControlBitmap هست که بصورت سراسری تعریف شده. شی browseFileDialog هم از نوع OpenFileDialog هست.
وقتی هم اجرا میشه ، توی دیزاینر ، کد به درستی اجرا میشه و تغییراتش دیده میشه (حتی شی transparentControl ام که روی فرم هست ، بیت مپِ مورد نظرش تغییر میکنه و دیده میشه) اما وقتی که بخوام برنامه را اجرا کنم (دکمه ی start و f5 را میزنم) ، برنامه که اجرا میشه ، این تغییرات دیده نمیشه و شی transparentControl ام دوباره به حالت پیش فرض خودش (وقتی که متد سازنده ی پیش فرض را اجرا کردم) تبدیل میشه و تغییر شکل میده.
من کجای این دو خط کد را بررسی کنم؟
کلا یه کم راهنمایی بیشتر کنین . اگه زحمت تون نیست ، اون فایلی که توی پیام خصوصی براتون آپلود کردم هم دانلود کنین ، ممنون میشم.


یه سئوال اینکه چرا وقتی یه کنترل TransparentControl را از toolbox به فرم (در دیزاینر) اضافه میکنم ، توی form1.designer.cs ، تقریبا همه ی پروپرتی هایی که دادم از هر 3 کلاسی که نوشتم را مقداردهی میکنه؟ حتی مقدار null را هم به پروپرتی ها اختصاص میده! نال که دیگه نال هه بصورت پیش فرض. مقداردهی کردن نمیخواد .
چیکار باید کنم که بهش بگم لازم نیست فلان پروپرتی ها را مقداردهی نکنی در دیزاینر؟
 

SU-57

Active Member
سلام استاد علی

1- در این کد چون str1 از نوع کلاسه پس به صورت رفرنس به parameter1 ارجاع داده می شه؟

کد:
string Method1(string parameter1)
{
    return parameter1;
}

private void button1_Click(object sender, EventArgs e)
{
    string str1 = "Reza";
    string str2 = Method1(str1);
    MessageBox.Show(str2.ToString());
}
بعد اینکه متد بالای رویداد بنویسیم اصولی تره یا پایین رویداد.

2- مثلا اینکه میگن سی شارپ 7 اومده یا ممکنه بعدا سی شارپ 8 بیاد چه چیزهایی به سی شارپ اضافه می شه و آیا ممکنه روش هایی که قبلا خوندیم عوض بشه در اینده.

3- غیر از اینکه باید همیشه به روز باشیم ولی کلا باید چیکار کنیم که سی شارپ رو یکبار برای همیشه یاد بگیریم طوری که دیگه مدام نریم سوال بپرسیم دقیقا مثل شما باشیم که نه تنها سوالی ندارید بلکه جواب همه سوال ها رو می دونید چون کامل سی شارپ رو بلد هستید. یا اینکه ممکنه یک سوالی هم به ندرت ندونید با یک سرچ ساده جوابش رو پیدا کنید. یا اینکه نه تا ابد باید همیشه از افراد مختلف سوال بپرسیم و این علم پایان نداره.
 
آخرین ویرایش:

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام استاد علی

1- در این کد چون str1 از نوع کلاسه پس به صورت رفرنس به parameter1 ارجاع داده می شه؟

کد:
string Method1(string parameter1)
{
    return parameter1;
}

private void button1_Click(object sender, EventArgs e)
{
    string str1 = "Reza";
    string str2 = Method1(str1);
    MessageBox.Show(str2.ToString());
}
بعد اینکه متد بالای رویداد بنویسیم اصولی تره یا پایین رویداد.

2- مثلا اینکه میگن سی شارپ 7 اومده یا ممکنه بعدا سی شارپ 8 بیاد چه چیزهایی به سی شارپ اضافه می شه و آیا ممکنه روش هایی که قبلا خوندیم عوض بشه در اینده.

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

سلام.
بله ، چون از نوعِ کلاس هست ، بصورت ریفرنس و اشاره گرش ارسال میشه.
فرقی نداره متد بالای یک رویداد نوشته بشه یا پایین اش. فقط توی کلاس و ... باید نوشته بشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
استاد علی ، من الان چی کار کنم؟
از اون شیوه ، راه حلی داره؟
یا اینکه همون روشی که اشاره کردید و مسیر فایل اش را ذخیره کنم؟
یه کم بیشتر توضیح میدین استاد باید چی کار کنم؟
 

the_king

مدیرکل انجمن
خیلی ممنون استاد از توضیح مفصل تون.
خوب منم همین رو میگم . مثالش Font هست . خیلی از کنترل هایی که شرکت های دیگه هم میزنن ، هست و ... .
شما همیشه میگین چرا دو تا کلاس مجزای دیگه زدم.
یه چیزهایی متوجه شدم . اما دقیقا متوجه نشدم باید چی کار کنم؟ روی چه کلاس و چه پروپرتی ای ، چه اتریباتس (یا اتریباتس هایی) و چه کارهای اضافه تری باید انجام بدم؟
اول مطمئن بشید که کدتون خطای نهفته نداره. در قدم بعدی برای کلاس TransparentControlBitmap تون باید کاری انجام بدید که مثل Font قابل بازتولید باشه.
براتون Font رو مثال زدم، خوب منطقی است که قبل از اینکه ابهام پیش بیاد باید کد Font رو ببینید، FontConverter اش رو ببینید.
این EditorAttributes را الان بجای اینکه روی پروپرتی TransparentControl.TransparentControlBitmap قرار بدم ، باید روی کلاس TransparentControl قرار بدم؟
کلا یه کم بیشتر راهنمایی کنین.
باید نیست، اختیاریه. هر دو جا هم می توانید Editor رو مشخص کنید، برای مشخصه و برای کلاس. می توانید هر دو رو انجام بدید یا یکی شون رو. اگر قرار باشه TransparentControlBitmap به اندازه Font در کلاس ها و مشخصه های مختلفی بکار بره بهتره که خود کلاس Editor اش رو مشخص کرده باشه، وگرنه وقتی کارکردش در یکی دو مشخصه بیشتر نباشه فرقی نمی کنه که مشخصه Editor رو تعیین کنه یا کلاس، مثل کلاس شما.

همونطور که میدونید ، قصد فروش این کنترل رو دارم .
برای اینکه سورس اش در دسترس عموم قرار نگیره ، بجز پیام خصوصی ، من به چه روشی میتونم به دست تون برسونم؟
توی پیام خصوصی ، من سئوالات را مطرح نکردم . فقط فایل رو آپلود کردم . سئوال را اینجا مطرح کردم.
نیازی نیست برای نشون دادن یک مشکل کد کنترل خودتون رو قرار بدید، یک مثال کوچیک و مستقل برای کدی که مشکل ایجاد میکنه بسازید، سریعترین راه برای پیدا کردن دلیل مشکل همینه که کد رو خلوت کنید. مثلا الان اینکه کنترل رسمش Transparent ئه یا دو تا کلاس جانبی داره یا کلاس ها چند تا مشخصه دارند یا رسم اش چطوریه که مهم نیست، شما یک کلاس کنترل ساده بدون مشخصه های اضافی لازم دارید که فقط یک کلاس جانبی داره برای یک مشخصه که داخل اون کلاس هم فقط یک مشخصه Bitmap داره که اونم با Editor تعیین میشه که وقتی تغییر کرد کنترل به ساده ترین شکل ممکن رسم اش تغییری می کنه، همین. مشکلش رو که پیدا کردید و حل شد، تغییرات لازم رو در پروژه اصلی تون می دهید. چیزی که لازمه پیوست کنید همچین پروژه مختصر ئه که ربطی هم به کنترل شما و کارکردش نداره.

توقع داشتم همون کدی که من نوشتم را بنویسه دیگه .
یعنی TransparentControlBitmap.DefaultBitmap = new Bitmap("file address") را بذاره.
چطور چنین چیزی ممکنه، شما داخل DefaultBitmap اون "file address" رو قرار نمیدید، Bitmap هم که مشخصه ای برای مسیر Path نداره که بشه از رویش کد ساخت، تازه اگر داشت هم شما فایل exe پروژه تون که نباید به مسیر "file address" وابسته باشه.

به هر حال . پس الان مشکل از resources.GetObject نیست . در اونجا ، مقدار اون فایل تصویر ، بصورت باینری ذخیره میشه و خونده میشه. (توی فایل Resources.resx ذخیره میشه؟)
من الان چه کدی را باید چک کنم؟ کلا اون قسمت از کد Editor ام که باعث میشه بیت مپی جدید را اختصاص بده ، 2 خط بیشتر نیست :

کد:
if (btnBrowseImage.Equals(this.btnBrowseDefaultBitmap) == true)
            {
                this.CurrentTransparentControlBitmap.DefaultBitmap = new Bitmap(this.browseFileDialog.FileName);
                this.transparentDefaultBitmap.TransparentControlBitmap.DefaultBitmap = this.CurrentTransparentControlBitmap.DefaultBitmap;
            }

CurrentTransparentControlBitmap هم شی جاری و برابر با پروپرتیِ TransparentControl.TransparentControlBitmap هست که بصورت سراسری تعریف شده. شی browseFileDialog هم از نوع OpenFileDialog هست.
وقتی هم اجرا میشه ، توی دیزاینر ، کد به درستی اجرا میشه و تغییراتش دیده میشه (حتی شی transparentControl ام که روی فرم هست ، بیت مپِ مورد نظرش تغییر میکنه و دیده میشه) اما وقتی که بخوام برنامه را اجرا کنم (دکمه ی start و f5 را میزنم) ، برنامه که اجرا میشه ، این تغییرات دیده نمیشه و شی transparentControl ام دوباره به حالت پیش فرض خودش (وقتی که متد سازنده ی پیش فرض را اجرا کردم) تبدیل میشه و تغییر شکل میده.
من کجای این دو خط کد را بررسی کنم؟
کلا یه کم راهنمایی بیشتر کنین . اگه زحمت تون نیست ، اون فایلی که توی پیام خصوصی براتون آپلود کردم هم دانلود کنین ، ممنون میشم.
اول یک پروژه مستقل و ساده رو شروع کنید، متد های سازنده پارامتر دار رو اصلا در این پروژه جدید استفاده نکنید، خلاصه ترین حالت ممکن. یک کلاس برای کنترل تون بسازید که یک مشخصه به اسم TransparentControlBitmap داره، بعد کلاس TransparentControlBitmap رو تعریف کنید که متد سازنده اش پارامتر نداره و فقط یک مشخصه DefaultBitmap داره که وقتی تغییر کرد باید در کنترل رسم بشه. بعد یک Editor برایش بسازید. حالا در تمامی روتین های این پروژه که خیلی کوچیک شده با try catch و Breakpoint وضعیت خطا رو بررسی کنید. بعد که مطمئن شدید خطایی نداره، برای TransparentControlBitmap صفت Serializable رو تعریف کنید و اگر دلتون میخواد می توانید ShouldSerializeDefaultBitmap رو هم برای مشخصه DefaultBitmap بنویسید که فقط وقتی true برگردونه که مشخصه مقدار null نداشته باشه.

یه سئوال اینکه چرا وقتی یه کنترل TransparentControl را از toolbox به فرم (در دیزاینر) اضافه میکنم ، توی form1.designer.cs ، تقریبا همه ی پروپرتی هایی که دادم از هر 3 کلاسی که نوشتم را مقداردهی میکنه؟ حتی مقدار null را هم به پروپرتی ها اختصاص میده! نال که دیگه نال هه بصورت پیش فرض. مقداردهی کردن نمیخواد .
چیکار باید کنم که بهش بگم لازم نیست فلان پروپرتی ها را مقداردهی نکنی در دیزاینر؟
چون Designer که نمیدونه کدوم لازمه و کدوم لازم نیست. پیشفرض بودن به این معنی نیست که ذخیره اش نکن. پیشفرض به این معنی است که Reset شدنی هست یا نه. اینکه null یا پیشفرض ئه دلیل بر این نیست که نباید ذخیره بشه.
در مورد متد ShouldSerializePropertyName گفتم. برای مشخصه هایی که ShouldSerializePropertyName ندارند فرض بر اینه که همیشه مقدارشون مهم ئه و باید ذخیره بشن.
کلا چند جور انتخاب داریم :
1- کلاسی است که کلا نمیخواهیم Serialize بشه، یعنی نمیخواهیم ذخیره بشه که کدی خاص و صفتی هم لازم نداره. کنترل ها جزو این گروه نیستند، چون با صفت DesignerSerializer براشون Designer ذخیره سازی رو انجام میده.
2- در سایر حالات کلاسی داریم که میخواهیم Serialize بشه ولی با شرایط مختلف، که صفت Serializable رو بهش میدیم. همچین کلاسی بصورت پیشفرض فیلد های داخلش همگی ذخیره میشه ولی برای اینکه روی serialization کنترل داشته باشیم چند انتخاب داریم :
2a- یک انتخاب اینه که بیاییم با ISerializable یک روال اختصاصی serialization بسازیم که در جای دیگری نیازی به تعریف شرایط برای مشخصه ها نباشه. مثل کاری که Font کرده.
2b- یک انتخاب دیگه اینه که بیاییم بگیم فلان فیلد داخلش رو هیچوقت serialize نکن (صفت NonSerialized) که صرفا بقیه رو ذخیره کنه یا با ShouldSerializePropertyName برای ذخیره کردنش اما و اگر بذاریم. اگه تعداد فیلد هایی که ذخیره نمیشن زیاد باشه یا ذخیره کردن مقادیر شرط پیچیده داشته باشه بهتره بجای 2b از روش 2a استفاده کنید که در یک متد یکجا همه تصمیم گیری ها انجام بشه.
هم 2a و هم 2b باید صفت Serializable رو داشته باشن، مگر اینکه مثل کنترل ها serialization جزو خصوصیات به ارث رسیده شون باشه.
 

the_king

مدیرکل انجمن
سلام استاد علی

1- در این کد چون str1 از نوع کلاسه پس به صورت رفرنس به parameter1 ارجاع داده می شه؟

کد:
string Method1(string parameter1)
{
    return parameter1;
}

private void button1_Click(object sender, EventArgs e)
{
    string str1 = "Reza";
    string str2 = Method1(str1);
    MessageBox.Show(str2.ToString());
}
string یک نوع داده خاص ئه، بصورت کلاس تعریف شده ولی برخلاف سایر کلاس ها که reference type هستند رفتارش شبیه value type ها است. یعنی کلاسش رو طوری کد نویسی کرده اند که شبیه value type ها مقدار بگیره، شبیه value type ها مقایسه کنه و شبیه value type ها مقدارش کپی بشه.
دلیل اینکه بصورت کلاس تعریف شده اینه که ممکنه رشته متنی داخلش خیلی طولانی و حجیم باشه که برای نگهداریش value type ها مناسب نیست. و رفتارش شبیه value type ها است چون اگر غیر از این بود برای کار با رشته ها و مقایسه کردنشون به مشکل برمیخوردیم.

بعد اینکه متد بالای رویداد بنویسیم اصولی تره یا پایین رویداد.
سلیقه ای ئه، اصول خاصی نداره. مهم اینه که خودتون در دسترسی به هر بخش راحت تر باشید. به هر روشی که باهاش راحت تر هستید اجزاء رو بچینید.

2- مثلا اینکه میگن سی شارپ 7 اومده یا ممکنه بعدا سی شارپ 8 بیاد چه چیزهایی به سی شارپ اضافه می شه و آیا ممکنه روش هایی که قبلا خوندیم عوض بشه در اینده.
عوض نمیشه، اما اگر روش های جدیدتر رو یاد نگیرید مزیت هایی رو از دست می دهید.
معمولا روش های جدید هم کد نویسی رو ساده تر می کنه و هم دست تون در طراحی بازتر میشه. روش قبلی تون همیشه کار تون رو راه می اندازه ولی شاید بهتره روش جدید رو یاد بگیرید، حالا اگر به نظرتون جالب نیومد ازش استفاده نکنید. مثلا من هیچوقت تمایلی برای استفاده از LINQ نداشتم، اما مواردی مثل nameof و ?? و .? و <= رو خیلی پسندیدم. اما یک عیب روش های جدید اینه که بخواهید به بقیه کد بدهید. وقتی کدتون رو در یک Visual Studio قدیمی باز کنند یک عالمه کد خطا دریافت می کنند.

3- غیر از اینکه باید همیشه به روز باشیم ولی کلا باید چیکار کنیم که سی شارپ رو یکبار برای همیشه یاد بگیریم طوری که دیگه مدام نریم سوال بپرسیم دقیقا مثل شما باشیم که نه تنها سوالی ندارید بلکه جواب همه سوال ها رو می دونید چون کامل سی شارپ رو بلد هستید. یا اینکه ممکنه یک سوالی هم به ندرت ندونید با یک سرچ ساده جوابش رو پیدا کنید. یا اینکه نه تا ابد باید همیشه از افراد مختلف سوال بپرسیم و این علم پایان نداره.
یکبار و برای همیشه که وجود نداره، هر سال تکنولوژی ها و پلتفرم ها و کتابخانه های جدیدی بوجود میاد، بخشی اش رو هیچوقت فرصت نمی کنید بررسی کنید چون با همون سرعت که بوجود میان منسوخ میشن و ارزش شون رو از دست میدن. اینه که هیچکسی هیچوقت همه چیز دون نمیشه، مجبور میشید روی یکسری گرایش ها متمرکز بشید و بقیه رو رها کنید.
برای منم اینطور نیست که هیچوقت به مشکلی برنخورم یا جواب همه سوالات رو آماده در ذهن داشته باشم.
من از کسی سوال نمی پرسم، چون اولا به ندرت با مشکلی روبرو میشم و معمولا پروژه ها خصوصیت جدید و ناشناخته ای برایم نداره، همه شون تکرار تجربیات گذشته است. ثانیا کسی رو سراغ ندارم که بخواد راهنمایی ام کنه و ثالثا تا بیام سوالم رو به کسی بفهمونم و بپرسم و ببینه و بررسی کنه و جواب بده لابد در بهترین شرایط چند ساعت طول میکشه. چه کاریه، بجاش خودم جواب رو جستجو می کنم و زودتر به جواب میرسم. تجربه کمکم می کنه که برای پیدا کردن جوابم معمولا فقط چند دقیقه جستجو کافی باشه. کد نویسی حفظ کردنی نیست، روش حل کردن مسائل رو یاد میگیرید. هر چقدر مسائل بیشتری رو حل کنید، راه حل هایی که به ذهنتون میرسه بیشتر میشه. کم کم به جایی میرسید که یا اصلا در طول هفته به مشکلی برنمیخورید یا اگر به مشکلی برخوردید فوری راه حلش رو پیدا می کنید.

سه تا مورد همیشه کمک تون می کنه، تجربیاتی که در گذشته داشتید، تسلط به خواندن متن های انگلیسی و بلد بودن روش درست جستجو در اینترنت.
وقتی قبلا چالش هایی مثل ساختن برنامه ها پیچیده رو گذرونده باشید خیلی از مشکلاتی که عموما پیش میاد رو تجربه کردید، هر چقدر که در اون موقع به دردسر برخورده باشید مهم نیست، الان دیگه راه حل شون رو میدونید و برای موارد مشابه هم به همون مشکل بر نمیخورید. اول یاد میگیرید که جایی که مشکل ساز بوده رو زود پیدا کنید، یعنی بفهمید ایراد از این بخش کد ئه، هنوز نمیدونید چرا ولی میفهمید ایراد اینجا است. وگرنه وقتی نمیدونید مشکل مربوط به چه موضوعی میشه به سادگی نمی توانید در موردش جستجو کنید.
از طرف دیگه یاد میگیرید که چطور راحت تر جستجو کنید و به راه حل برسید. اینکه برای جواب کجاها رو جستجو کنید، چه کلماتی رو جستجو کنید، کجاهای مطلب رو نخونید و کجاها رو بخونید و اینکه چقدر از چیزی که میخونید مطلب رو متوجه میشید هم خودش خیلی مهمه.
 

جدیدترین ارسال ها

بالا