Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Single Instance ενός Component σε μια φόρμα - Πως?

Îåêßíçóå áðü ôï ìÝëïò mod. Τελευταία δημοσίευση από το μέλος mod στις 18-07-2006, 11:23. Υπάρχουν 7 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  13-07-2006, 22:49 14707

    Single Instance ενός Component σε μια φόρμα - Πως?

    Προσπαθώ αυτές τις μέρες να φτιάξω ένα Component το οποίο υλοποιεί το IExtenderProvider. Έχω τελειώσει με τα βασικά κομμάτια (CanExtend, Get/Set, UITypeEditors κλπ). Το θέμα είναι οτι προσπαθώ τώρα να το αλλάξω έτσι ώστε να μη μπορεί πάνω από ένα instance του πάνω σε κάθε φόρμα. Κατέληξα στις δύο παρακάτω λύσεις:

        public MyExtender(System.ComponentModel.IContainer container)
        {
                ///
                /// Required for Windows.Forms Class Composition Designer support
                ///
               foreach (Component c in container.Components)
                {
                    if (c is MyExtender)
                    {
                        throw new InvalidOperationException("Only one instance of MyItemExtender is allowed per Container");
                    }
                }
                container.Add(this);
                InitializeComponent();
        }


        public MyExtender(System.ComponentModel.IContainer container)
        {
                ///
                /// Required for Windows.Forms Class Composition Designer support
                ///
                bool mustDestroy = false;

                foreach (Component c in container.Components)
                {
                    if (c is MyExtender)
                    {
                        MessageBox.Show("Only one instance of
    MyItemExtender is allowed per Container"
    , "Error",
    MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        mustDestroy = true;
                        break;
                    }
                }
                if (mustDestroy)
                {
                    container.Remove(this);
                    IDesignerHost host = container as IDesignerHost;
                    if (host != null)
                    {
                        host.DestroyComponent(this);
                    }
                    return;
                }
                else
                {
                    container.Add(this);
                }
                InitializeComponent();
        }


    Με λίγα λόγια στην πρώτη περίπτωση πετάω κατευθειαν Exception αν βρω κάποιο άλλο component του ίδιου τύπου στον container ενώ στην άλλη αν βρω κάποιο άλλο Instance ζητάω από τον container & designer να το αφαιρέσουν.

    Το πρόβλημα είναι οτι η πρώτη λύση δουλεύει από την άποψη οτι τελικά δεν προστίθεται νέο component στη φόρμα αλλά έχει το ελάττωμα οτι το Exception συλαμβάνεται από τον Designer και εμφανίζεται ένα MessageBox με stack trace. H δεύτερη λύση από την άλλη μου φαίνεται πιο σωστή και ειδοποιεί το χρήστη με το κατάλληλο μήνυμα αλλά τελικά προστίθεται ένα νέο component (Και μάλιστα non-initialized) στη φορμα. Υπάρχει μήπως καμιά καλύτερη λύση για να μην αναγκάζομαι να πετάω εξαίρεση και παράλληλα να μην προστίθεται το component στη φόρμα?
  •  14-07-2006, 12:51 14724 σε απάντηση της 14707

    Απ: Single Instance ενός Component σε μια φόρμα - Πως?

    Σχετικά με τον πρώτο τρόπο για να μην σου βγάζει το μήνυμα στον designer όπως αναφέρεις βάλε τον κώδικα σε ένα Try...Catch block. Έτσι γίνεται στην VB. Στην C# δεν γνωρίζω.

    Υπάρχει και μία άλλη λύση αν θέλεις να δοκιμάσεις. Μπορείς να διαβάσεις περισσότερα για αυτήν μέσα εδώ, σε αυτό το site και αν θέλεις να το ψάξεις στο internet διάβασε για την τεχνική singleton.

  •  14-07-2006, 16:35 14754 σε απάντηση της 14707

    Απ: Single Instance ενός Component σε μια φόρμα - Πως?

    infoCENTER αν διαβάσεις τον κώδικα θα δεις οτι στην πρώτη περίπτωση εγώ υψώνω το exception προκειμένου να το πιάσει ο Form Designer και να μην αφήσει το νέο component να μπει στη φόρμα.

    Η singleton δεν είναι λύση για το συγκεκριμένο πρόβλημα, αφού θέλω να υπάρχουν πολλά διαφορετικά instances του component - τόσο στην ίδια όσο και σε διαφορετικές εφαρμογές -, απλά θέλω να διασφαλίσω οτι θα μπορεί να μπει μόνο ένα instance πάνω σε κάθε φόρμα.
  •  17-07-2006, 00:10 14823 σε απάντηση της 14707

    Απ: Single Instance ενός Component σε μια φόρμα - Πως?

    Θα μπορούσες ίσως να κάνεις κάτι πιο απλό. Να έχεις ένα Flag στην φόρμα σου, το οποίο θα παίρνει την τιμή true την πρώτη φορά που γίνεται add το MyExtender Component. Έπειτα απλά θα κάνεις έλεγχο για την τιμή του Flag και ανάλογα θα επιτρέπεις ή θα απαγορεύεις την προσθήκη του Component.

    π.χ.

    public bool hasExtender;

    public MyExtender(System.ComponentModel.IContainer container)
        {

              if(!hasExtender)

              {

                hasExtender=true;
                container.Add(this
    );
                InitializeComponent();

              }
        }

  •  17-07-2006, 11:42 14836 σε απάντηση της 14707

    Απ: Single Instance ενός Component σε μια φόρμα - Πως?

    evliatsas το δοκίμασα αρχικά... κατ'αρχήν αυτό που λες δε μπορεί να γίνει με ενα απλό boolean, το είχα κάνει με ένα static Dictionary(Form, bool) αλλά και πάλι δεν είναι λύση γιατί ακόμα και αν δεν τρέξει η εντολή container.Add(this); με κάποιο τρόπο και πάλι μπαίνει το component πανω στη φόρμα!
  •  17-07-2006, 11:58 14837 σε απάντηση της 14836

    Απ: Single Instance ενός Component σε μια φόρμα - Πως?

     mod wrote:
    κατ'αρχήν αυτό που λες δε μπορεί να γίνει με ενα απλό boolean, το είχα κάνει με ένα static Dictionary(Form, bool)

    Επειδή ακριβώς δεν γνωρίζω πως έχεις οργανωμένο το namespace σου, το Declaration το έγραψα στην πιο απλή μορφή του, περισσότερο για να εξηγήσω τι εννοούσα με την λέξη "flag".

     mod wrote:
    αλλά και πάλι δεν είναι λύση γιατί ακόμα και αν δεν τρέξει η εντολή container.Add(this); με κάποιο τρόπο και πάλι μπαίνει το component πανω στη φόρμα

    Από κάπου καλείς την δημιουργία του Component, κάποιο button Event ή οτιδήποτε. Μπορείς εκεί να εκτελέσεις τον έλεγχο του flag πρίν ξεκινήσεις το instantiate του Component και όχι απλά να απαγορέψεις την προσθήκη του στο Container. Άν και πάλι σου προστίθεται Component στην φόρμα σου, το πιο πιθανό είναι να το καλείς δύο φορές από διαφορετικές πλευρές. 

  •  17-07-2006, 14:16 14847 σε απάντηση της 14837

    Απ: Single Instance ενός Component σε μια φόρμα - Πως?

    Συγνώμη δεν κατάλαβα ότι ήθελεες αυτό. Αλλά ας μην αφήσουμε ακόμα την τεχνική singleton. Θα μπορούσες να ανεβάσεις τον κώδικα που εξασφαλίζει ότι θα φορτωθεί ένα instance του component σε επίπεδο φόρμας. Έτσι θα μπορούσες να είχες αυτό που ήθελες. Ίσως αυτό να σου κάνει.
  •  18-07-2006, 11:23 14872 σε απάντηση της 14837

    Απ: Single Instance ενός Component σε μια φόρμα - Πως?

     evliatsas wrote:
    Από κάπου καλείς την δημιουργία του Component, κάποιο button Event ή οτιδήποτε. Μπορείς εκεί να εκτελέσεις τον έλεγχο του flag πρίν ξεκινήσεις το instantiate του Component και όχι απλά να απαγορέψεις την προσθήκη του στο Container. Άν και πάλι σου προστίθεται Component στην φόρμα σου, το πιο πιθανό είναι να το καλείς δύο φορές από διαφορετικές πλευρές. 


    To construction του component γίνεται από τον form designer του Visual Studio όταν κάνω drag-drop ένα component πάνω στην εκάστοτε φόρμα. Από εκεί και πέρα το τι γίνεται στο runtime δε με απασχολεί (τουλάχιστον όχι τόσο πολύ ακόμα). Αυτό που με ενδιαφέρει είναι όταν σχεδιάζει κάποιος μια φόρμα να μη μπορεί να βάλει πάνω από ένα τέτοιο component σε αυτήν. Είναι δηλαδή καθαρά design-time το θέμα.
    Από το debugging που εκανα κάνοντας attach ένα άλλο instance του debugger στο visual studio παρατήρησα οτι ενώ καλώ τη μέθοδο DestroyComponent φαίνεται οτι ο designer κρατά κάποιο reference στο τρέχον αντικείμενο και τελικά το ξαναβάζει στη φόρμα σε μεταγενέστερο χρόνο.
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems