[.NET] Lijstje van Components?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Hey,

Ik heb een Component die men op een Form kan slepen, en ik wil graag dat er maar 1 instance van deze Component tegelijk op de form kan bestaan. Ik wil dus dat er een exception gegooid wordt als men een tweede instance op een Form wil slepen.

Daarnaast is er ook de mogelijkheid om een instance in code te maken. Er kan dan een Form worden meegegeven in de constructor. In dat geval wil ik ook kijken of er nog geen instances van mijn component op die Form staan.

Met controls zou dit vrij gemakkelijk zijn; een simpel loopje door de Controls collectie van de parent form om te kijken of er al een control is met hetzelfde type. Maar voor zover ik kan zien zijn is er geen Components collectie of iets dergelijks...?

Voor de duidelijkheid: deze functionaliteit moet dus in de Component komen, en niet in de form. Ik weet hoe ik de parent form van een component krijg (de Site property overriden), maar ik weet dus niet hoe ik aan een lijstje met components op die Form kom...

Is dit wel mogelijk?

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Hm, ik ben al een klein beetje verder, maar nog niet helemaal.

De volgende code gebruikt de Site.Container.Components property van de parent form om te kijken of er al een andere component is. Zo ja, dan wordt een exception gegooid.
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Imports System.ComponentModel
Imports System.ComponentModel.Design

Public Class TestComponent
    Inherits Component

    Public Sub New()

    End Sub

    Public Sub New(ByVal frm As Form)
        Me.CheckComponents(frm)
    End Sub

    Private _ParentForm As Form
    Public Property ParentForm() As Form
        Get
            Return _ParentForm
        End Get
        Set(ByVal value As Form)
            _ParentForm = value

            ' ParentForm changed, check for other components here
            Me.CheckComponents(_ParentForm)
        End Set
    End Property

    Private Sub CheckComponents(ByVal frm As Form)
        If frm IsNot Nothing Then
            If frm.Site IsNot Nothing AndAlso frm.Site.Container IsNot Nothing Then
                For Each c As Component In frm.Site.Container.Components
                    If TypeOf c Is TestComponent AndAlso c IsNot Me Then
                        Throw New Exception("Duplicates!")
                    End If
                Next
            End If
        End If
    End Sub

    'Override the Site property to know when it changes so you can get the parent form
    Public Overrides Property Site() As System.ComponentModel.ISite
        Get
            Return MyBase.Site
        End Get
        Set(ByVal value As System.ComponentModel.ISite)
            MyBase.Site = value

            If value Is Nothing Then Return

            Dim host = TryCast(value.GetService(GetType(IDesignerHost)), IDesignerHost)
            If host IsNot Nothing Then
                Dim componentHost = host.RootComponent
                If componentHost IsNot Nothing Then
                    Me.ParentForm = TryCast(componentHost, Form)
                End If
            End If
        End Set
    End Property
End Class


Dit werkt tijdens design-time. Als ik al een instance op mijn form heb en er dan een tweede op probeer te slepen krijg ik de exception te zien en wordt de tweede instance niet aangemaakt.

Maar het werkt niet tijdens run-time. Als ik de tweede constructor aanroep en een Form pass, bijvorbeeld dit in Form_Load:
Visual Basic:
1
Dim c As New TestComponent(Me)

dan blijkt dat de Site property van de parent form null is en gebeurt er dus niets (de eerste check in regel 30 is False). Dat lijkt misschien logisch (de component heeft namelijk nog geen parent), maar ik gebruik dan ook niet de parent form van de component, maar juist de form die in de constructor meegegeven wordt, dus het zou toch gewoon moeten werken?

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • eek
  • Registratie: Februari 2001
  • Laatst online: 06-04-2020

eek

@MagickNET

Waarom wil je deze 'controle' inbouwen? Gaat er iets fout als je component er twee keer op staat?

Skill is when luck becomes a habit.


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Het is gewoon niet de bedoeling om meerdere instances per form te gebruiken. Of er iets mis gaat weet ik zo niet, op het moment denk ik niet (maar dat kan altijd nog veranderen). Ik kan natuurlijk tegen gebruikers zeggen dat ze maar 1 instance per form moeten gebruiken, maar men luistert niet altijd dus zou het mooi zijn als ik dat gewoon kon forceren, dan zal het altijd kloppen.

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 13-09 11:16

mulder

ik spuug op het trottoir

Waarom dan en designtime en runtime? En zou anders ShowDialog() misschien een handige manier zijn :)

oogjes open, snaveltjes dicht


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
De component hoeft niet altijd op een form gezet te worden tijdens design-time, hij wordt ook wel eens in code gemaakt, pas wanneer hij nodig is. Ook dan wil ik dat er maar 1 instance gemaakt kan worden.

En ShowDialog? Dat begrijp ik niet. Ik heb het toch niet over een form?

[ Voor 3% gewijzigd door NickThissen op 08-07-2010 20:24 ]

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • kluyze
  • Registratie: Augustus 2004
  • Niet online
Dus je wilt een singleton maken?

Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Min of meer, maar niet precies. Ten eerste geloof ik niet dat dat mogelijk is voor een Component (of voor een Control)? Ik heb het vroeger eens geprobeerd, en (als ik het me goed herinner) ik kon wel een instance op de form slepen (nou ja, in de 'component tray' of hoe dat ook heet), maar er werd dan in code (in de designer code) geen instance aan de variabele toegekend waardoor die null bleef.

Ten tweede is het best mogelijk dat twee forms twee verschillende instances van de component hebben, dus daar gaat een singleton ook al niet werken.

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • eek
  • Registratie: Februari 2001
  • Laatst online: 06-04-2020

eek

@MagickNET

Je zou als het echt moet via een private static Dictionary bij kunnen houden welke forms je per component al bent tegengekomen. Maar er zal vast een mooiere / betere oplossing zijn.

Skill is when luck becomes a habit.


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Ja zoiets had ik ook al bedacht, een static (of shared in VB) List(Of Form) bijhouden in de component. Dat is inderdaad niet de mooiste oplossing, vandaar dat ik een betere zoek.

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • Korben
  • Registratie: Januari 2001
  • Laatst online: 13-07 01:53

Korben

() => {};

Je zou de ParentChanged event van je control kunnen afvangen, en vervolgens bij die nieuwe parent recursief door de control tree gaan lopen om te kijken of je een instantie van je control tegenkomt (waarbij je wel checkt of je dat niet zelf bent).

Overigens is dit niet de snelste methode, dat is toch een lijst met forms waarop je aanwezig bent.

[ Voor 12% gewijzigd door Korben op 09-07-2010 14:05 ]

.oisyn: Échte programmeurs haten PHP met een passie. Ben jij soms geen echte programmeur?


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Korben schreef op vrijdag 09 juli 2010 @ 14:03:
Je zou de ParentChanged event van je control kunnen afvangen, en vervolgens bij die nieuwe parent recursief door de control tree gaan lopen om te kijken of je een instantie van je control tegenkomt (waarbij je wel checkt of je dat niet zelf bent).

Overigens is dit niet de snelste methode, dat is toch een lijst met forms waarop je aanwezig bent.
Ik heb het over een Component, niet een Control. Een Component heeft geen Parent en geen ParentChanged event. Die kan ik wel zelf maken door de Site property te overriden, maar dan nog moet ik een lijstje met alle Components (niet Controls) op een Form krijgen, en blijkbaar is dat niet mogelijk tijdens run-time ofzo..? :?

Mijn iRacing profiel

Pagina: 1