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

نام تاپیک: آموزش : نحوه ی کنترل کردن فرمها و مشکلات متداول

  1. #1

    آموزش : نحوه ی کنترل کردن فرمها و مشکلات متداول


    سلام

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

    در ادامه ی بحث به این موارد پرداخته میشود :
    1- نحوه ی بار کردن فرمهای فرزند بصورت تنها یکبار در حافظه (به کمک Singleton Pattern)
    2- و نحوه ی کار کردن با کنترلهای یک فرم و روش صحیح پاس دادن مقادیر بین فرمهای یک برنامه
    و ...

    امیدوارم که مفید باشه.
    دوستان اگر نظر موافق یا مخالفی داشتند خوشحال میشم که مطرح کنند.
    ...مرا به خانه ام ببر، اگرچه خانه؛ خانه نیست

  2. #2

    کنترل فرم ها از طریق الگوی سینگلتون

    فکر میکنم اکثر دوستان با این pattern آشنا باشند.
    (اونایی که از این الگو اطلاعی ندارن به این لینک مراجعه کنند :
    http://www.dofactory.com/Patterns/PatternSingleton.aspx)

    اما بصورت خیلی خلاصه : در این الگو هدف رسیدن به وضعیتی است که بتونیم تضمین کنیم از یک کلاس فقط و فقط یک (و یا در حالتی خاص: تعدادی مشخص و کنترل شده) آبجکت ساخته شود. (ضمن اینکه روش مناسبی برای عملیاتی ست که نیاز به یک دسترسی سراسری دارند)
    Ensure a class has only one instance and provide a global point of access to it
    .

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

    خب از اونجا که هدف تاپیک چیز دیگریست بحث راجع به این pattern رو همینجا خاتمه میدم.

    در این پست سعی داریم یک برنامه بسازیم که متشکل از یک فرم والد و سه فرم فرزند باشه.
    (و با این شرط که : فرم والد تنها میتواند یک نمونه از هر فرزند را در حافظه بار کند.)

    اولن کاری که بنظر میرسه اینه که در تک تک فرمهای فرزند الگوی سینگلتون رو - مانند نمونه ی زیر - تکرار کنیم :
    namespace Ticket
    {
    public partial class frmBoat : Form
    {
    #region Singleton Form
    private static frmBoat formInstance = null;
    public static frmBoat GetInstance()
    {
    if (formInstance == null)
    {
    formInstance = new frmBoat();
    }
    return formInstance;
    }

    private frmBoat()
    {
    InitializeComponent();
    }
    #endregion
    }
    }
    البته راههای زیادی - و با توجه به حالتهای خاص - برای ایجاد کلاسهای سینگتون وجود دارد.

    اما مشکل عمده ای که روش بالا دارد این است که باید برای تمامی فرمها (و یا بصورت کلی : برای تمامی کلاسهای مورد نظر) این الگو را تکرار کنیم.

    چه خوب بود اگه میتونستیم یکبار این الگو رو مینوشتیم و همه جا از اون استفاده میکردیم.
    لذا بدون مقدمه میریم سراغ نوشتن یک Generic Singleton :

        public class SingletonProvider<T> where T : new()
    {
    SingletonProvider() { }

    public static T Instance
    {
    get { return SingletonCreator.Instance; }
    }

    class SingletonCreator
    {
    private SingletonCreator() { }
    private static T instance;
    internal static T Instance
    {
    get
    {
    if (instance == null)
    instance = new T();
    else if (instance is Form)
    if ((instance as Form).IsDisposed)
    instance = new T();
    return instance;
    }
    }
    }
    }
    واقعا چقدر استفاده از کلاسهای ژنریک لذت بخشه. اینطور نیست ؟!

    و کلاسی رو نیز به این شکل مینویسیم برای کنترل فرمهای فرزند :
        public class FormManagementHelper
    {
    public static Form ShowChildForm(Form _parent, Form _child)
    {
    _child.MdiParent = _parent;
    _child.Show();
    _child.Activate();
    return _child;
    }

    public static void ShowChild1(Form _parent)
    {
    ShowChildForm(_parent, SingletonProvider<Child1>.Instance);
    }

    public static void ShowChild2(Form _parent)
    {
    ShowChildForm(_parent, SingletonProvider<Child2>.Instance);
    }

    public static void ShowChild3(Form _parent)
    {
    ShowChildForm(_parent, SingletonProvider<Child3>.Instance);
    }
    }
    خب فکر میکنم خود کد به تنهایی گویا باشه.
    فقط اینکه Child1 , Child2, Child3 اسم فرمهای فرزند هستند که توسط کلاس ژنریک سینگلتون یک Instance از اونها برگشت داده میشه.

    و در ادامه در کد فرم والد این کدها رو برای نشون دادن فرمهای فرزند مینویسیم :
            private void child1ToolStripMenuItem_Click(object sender, EventArgs e)
    {
    FormManagementHelper.ShowChild1(this);
    }

    private void child2ToolStripMenuItem_Click(object sender, EventArgs e)
    {
    FormManagementHelper.ShowChild2(this);
    }

    private void child3ToolStripMenuItem_Click(object sender, EventArgs e)
    {
    FormManagementHelper.ShowChild3(this);
    }
    ...مرا به خانه ام ببر، اگرچه خانه؛ خانه نیست

  3. #3
    من سورس کد نهایی برنامه بالا رو هم آپلود میکنم واسه دوستانی که شاید مایل باشند با جزییات بیشتر برنامه رو ببینند.
    و یکی از دوستان هم نحوه به ارث بردن فرمهای برنامه از یک فرم رو پرسیده بودند که تو همین مثال (با نام BaseForm) استفاده شده است.
    فایل های ضمیمه فایل های ضمیمه
    ...مرا به خانه ام ببر، اگرچه خانه؛ خانه نیست

  4. #4

    Wink

    <T> where T
    شبیه به اینها رو قدیما توی ++C استفاده میکردیم. نمیدونستم تو #C هم میشه استفاده کرد (ندیده بودم)
    میشه در این مورد بیشتر توضیح بدی
    ممنون
    آن لحظه که تنها اعتبار کسی که مساله ای را مطرح کرده است، شما را در اشتباه بودن ایده هایتان قانع کرد،
    آن لحظه،
    لحظه وداع شما با دنیای خلاقیت و پیشرفت خواهد بود. . .

    برنولی

  5. #5

  6. #6
    نقل قول نوشته شده توسط bermooda مشاهده تاپیک
    تا اونجایی که من یادمه تو ++C بهشون میگفتیم Template (البته الانم میگیم )
    ولی باز تا اونجایی که یادمه پیاده سازی Template با Generic های #C متفاوته (هر چند از نظر مفهومی تقریبا مثل همن )
    خب منم اسمشو تقریبا یادم بود ولی گفتم شاید اشتبا باشه (آخه خیلی وقته دستم به ++C نخورده بعد از ترم 1 تا حالا)
    خب در مورد پیاده سازی و اجراشون مثله ++C می مونه یا چطوریه؟
    آن لحظه که تنها اعتبار کسی که مساله ای را مطرح کرده است، شما را در اشتباه بودن ایده هایتان قانع کرد،
    آن لحظه،
    لحظه وداع شما با دنیای خلاقیت و پیشرفت خواهد بود. . .

    برنولی

  7. #7

  8. #8
    کاربر دائمی آواتار bahar_engineer
    تاریخ عضویت
    دی 1387
    محل زندگی
    تهران
    پست
    657

    نقل قول: آموزش : نحوه ی کنترل کردن فرمها و مشکلات متداول

    من همینطور کلاسها رو توی پروژه قرار دادم اما وقتی یک بار مثلاً صفحه ثبت نام رو باز می کنه بار دوم دیگه بازش نمی کنه ... یعنی نمایشش نمی ده و هیچ عملی انجام نمی شه

    چرا ؟؟

    تو پروژه من 3 تا کاربر می تونن ثبت نام کنن ... و هر کدام از بخش ویژه خودشون بالا بیان ... حالا اگه یکی از کاربران اول نرم افزار رو نصب کنه و بعد از نصب در ابتدای بالا اومدن صفحه ثبت نام می آد و اون ثبت نام می کنه ... حالا اگه همین موقع کاربر دوم بیاد ثبت نام کنه باید اون صفحه ثبت نام دوباره نمایش داده بشه چون صفحه ای هم هست که بعد از ثبت نام صفحه اصلیه نرم افزار رو باز می کنه نمی تونم close کنم... پس باید پنهان بشه از دید کاربر و موقع فراخوانی دوباره نمایش داده بشه


    البته من در حالت عادی هم با این سینگلتون مشکل دارم یعنی اصلاً hidden هم نکردم صفحه ثبت نام رو اما با سینگلتون فقط همون بار اول باز می شه و اگه دوباره بخوام ثبت نام کنم نمیاد بالا

    منتظر راه حلم ... THX

  9. #9

    Exclamation نقل قول: آموزش : نحوه ی کنترل کردن فرمها و مشکلات متداول

    این فرم یک فرم سینگلتون با محدودیت خاصی است و فقط به این معنا نیست که یک فرم دوبار new نشود بلکه اگر یک صفت آن(isdispose) مثبت باشد می توان آن را دوباره new کرد. بنابراین یک سینگلتون با این شرایط است .
    به نظرم روشی که ارائه کردید مشکلاتی را داراست که در ادامه توضیح می دهم
    1-هر وقت فرم جدیدی را بخواهید به مجموعه اضافه کنید نیاز دارید که کلاس FormManagementHelper را باز تعریف کنید و از نگاه شی گرا این وضعیت مطلوبی نیست
    2- بعد از نمایش فرم دیگر نمی توان به اشاره گر فرم دسترسی داشت(مثلا احیانا بخواهیم بعد از بسته شدن فرم مقدار یک خصوصیت فرم را بخوانیم)، البته می توان با ایجاد یک خصوصیت(مثل GetChild1) در کلاس FormManagementHelper اشاره گر به آن فرم را برای در خواست کننده بر گرداند که اگر این کار صورت گیرد مشکل دیگری را اضافه می کند، و آن اینکه ممکن است در طول برنامه دو ارجاع به یک فرم ایجاد شود و اگر اولین ارجاع فرم را به هر دلیلی مثل بستن فرم dispose کند و ارجاع دوم بخواهد بعد این کار تابع show فرم را مستقلا فراخوانی کند به exception بر می خورد. پس اساسا ورود بحث Isdispose به کلاس سینگلتون کار اصولی نیست و فقط "کار راه انداز" عمل می کند.
    3- خوانایی کد شما از درجه پایینی برخوردار است
    پس مسئله را دوباره تعریف می کنیم:
    می خواهیم فرمی داشته باشیم که تا هنگامی که dispose نشده هر فراخوانی از آن فرم، ما را به یک آبجکت منحصر به فرد رهنمون کند. و در صورتی که dispose شد یک آبجکت جدید تحویلمون بده.(البته دیگه اسمش singleton نیست!)
    راه حل مناسب تر:
    به نظر من بهتره یک فرم Singleton تعریف شود و کاربر هر زمانی که مایل بود فرمی به شکلی که در بالا تعریف کردیم داشته باشد آن را به صورت item به برنامه خود اضافه کند و بدون درگیر شدن با محتوای کلاسی که ما تعریف کردیم از آن استفاده کند. این کار خصوصیت استفاده مجدد را بالا می برد.
    ناگفته نماند که مشکل ارجاعات که در بند 3 به ان اشاره شد همچنان پابرجاست



    public partial class FormSingleton : Form
    {
    FormSingleton()
    {
    InitializeComponent();
    }
    class SingletonCreator
    {
    static SingletonCreator() { }
    internal static
    FormSingleton uniqueInstance = new FormSingleton();
    }
    public static FormSingleton UniqueInstance
    {
    get
    {
    if (SingletonCreator.uniqueInstance == null)
    SingletonCreator.uniqueInstance = new FormSingleton();
    else
    if (SingletonCreator.uniqueInstance.IsDisposed)
    SingletonCreator.uniqueInstance = new FormSingleton();
    return SingletonCreator.uniqueInstance;
    }
    }
    }

    این کد را code behind یک فرم جدید وارد می کنیم و با ساخت یک template item از آن می توان آن را در هر پروژه ایی استفاده کرد.
    فایل template را ضمیمه می کنم
    فایل های ضمیمه فایل های ضمیمه
    آخرین ویرایش به وسیله reza_arab : شنبه 04 اردیبهشت 1389 در 21:27 عصر دلیل: تذکر

  10. #10
    کاربر دائمی
    تاریخ عضویت
    آبان 1387
    محل زندگی
    خراسان رضوی
    پست
    677

    نقل قول: آموزش : نحوه ی کنترل کردن فرمها و مشکلات متداول

    راستش من نفهمیدم فایل هایی که دوستمون گذاشتند چه طوری استفاده کنم . من با singelton کار نکردم .کاش خود پروژه رو میزاشتید .من خیلی دوست دارم با singelton آشنا بشم

  11. #11

    نقل قول: آموزش : نحوه ی کنترل کردن فرمها و مشکلات متداول

    با سلام خدمت استادهاي گرامي
    من يك مبتدي هستم 2 تا فرم دارم مي خوام در فرم دوم 2 رشته از من گرفته بوسيله تكست باكس و آنهارا وارد يك ليست باكس در فرم اول كند
    ولي در فرم دوم ليست باكس من رو نميشناسه
    يعني كلا هيچ شئي از فرم ديگه رو نميشناسه و تغير نمي ده....
    فقط شئي هاي خودش رو مي شناسه

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

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