VB.net select/case doesn't fall through! WTF



  • <FONT size=2>

    y = Math.Round(TextBox1.Text.ToString * 1)

    </FONT><FONT color=#0000ff size=2>Select</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Case</FONT><FONT size=2> y

    </FONT><FONT color=#0000ff size=2>Case</FONT><FONT size=2> 0 </FONT><FONT color=#0000ff size=2>To</FONT><FONT size=2> 1

    Button1.Visible = </FONT><FONT color=#0000ff size=2>True

    </FONT><FONT size=2>

    </FONT><FONT color=#0000ff size=2>Case</FONT><FONT size=2> 2 </FONT><FONT color=#0000ff size=2>To</FONT><FONT size=2> 8

    Button2.Visible = </FONT><FONT color=#0000ff size=2>True</FONT>

    <FONT color=#0000ff>end select</FONT>

    this won't set both to visible... To which i put forth this question

    Let's say i have 8 cases that i want to fall through in order (like in C) starting at the least likely and ending at the most likely... is there any way to do this in VB.NET without If .. Else if?

    Also, is there a way to access buttons by ID rather than names? Like see how it says button1, button2? I remember programming in the old days where you could do stuff like

    button[y] . visible = true

    Or similar. button1 is a variable name, but does VB.net (or even C#) have anything where i can just do a for loop and set 1 button each run through?

    for (i=0;i < 8; ++i){

    button[i].visible = true

    }

    anything like that? it'd be a huge help.

    <FONT color=#0000ff size=2> 

    </FONT>


  • Starting with the Select/Case question; I don't think that is possible in Visual Basic. Of course, you could do something like adding a goto statement at the end of every case, skipping the next case statement. However, that would probably make the front page on WorseThanFailure if you ever put something like that in production ;).

     

    As for the buttons question, it is not a language feature, but a question of how you design the program. By adding all your buttons to an array, you could get the desired effect. You may even be able to generate an array like that dynamically, by using reflection. I don't know if that's a good idea though.



  • The real WTF here is that THIS thread and only THIS thread on this forum crashes IE on the machine that im currently using



  • well, FUCK.

    <FONT color=#0000ff size=2>

    Dim</FONT><FONT size=2> c </FONT><FONT color=#0000ff size=2>As</FONT><FONT size=2> Windows.Forms.Control

    </FONT><FONT color=#0000ff size=2>For</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Each</FONT><FONT size=2> c </FONT><FONT color=#0000ff size=2>In</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Me</FONT><FONT size=2>.Controls

    h = h + c.Name.ToString + Environment.NewLine

    </FONT><FONT color=#0000ff size=2>Next

    </FONT><FONT size=2>

    MsgBox(h)

    This works (as in i can see the button names)

    But i don't know crap about For Each...

    see the bit that says c.name.tostring?

    How do i set the value of c by hand so i can use it in another way - re: my original question

    Damn it. I might just have to switch to C#

    <FONT size=2>

    </FONT><FONT color=#0000ff size=2>For</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Each</FONT><FONT size=2> c </FONT><FONT color=#0000ff size=2>In</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Me</FONT><FONT size=2>.Controls

    c.Visible = </FONT><FONT color=#0000ff size=2>True

    </FONT><FONT size=2>

    </FONT><FONT color=#0000ff size=2>Next</FONT>

    <FONT color=#0000ff size=2>Works to set everything visible.. now how do i do this without a for each loop?</FONT>

    <FONT color=#0000ff size=2>c = "some control name"</FONT>

    <FONT color=#0000ff size=2>c.visible = true</FONT>

    <FONT color=#0000ff size=2>Like that? anyone? anyone?</FONT>

    <FONT color=#0000ff size=2>and how the hell do i have a control array?

    </FONT></FONT>


  • @hardcorewizard said:

    Starting with the Select/Case question; I don't think that is possible in Visual Basic. Of course, you could do something like adding a goto statement at the end of every case, skipping the next case statement. However, that would probably make the front page on WorseThanFailure if you ever put something like that in production ;).

     

    As for the buttons question, it is not a language feature, but a question of how you design the program. By adding all your buttons to an array, you could get the desired effect. You may even be able to generate an array like that dynamically, by using reflection. I don't know if that's a good idea though.

    I don't want to skip cases 2 through 8 if case 1 is the first one it hits

    If i have the number 8, given my OP, i want both button1 and button2 to be set to visible



  • @GeneWitch said:

    Let's say i have 8 cases that i want to fall through in order (like in C) starting at the least likely and ending at the most likely... is there any way to do this in VB.NET without If .. Else if?

    IIRC, this kind of fall through is not allowed in C#. I guess it isn't possible in VB.net, either. 

    Also, is there a way to access buttons by ID rather than names? Like see how it says button1, button2? I remember programming in the old days where you could do stuff like

    button[y] . visible = true

    Or similar. button1 is a variable name, but does VB.net (or even C#) have anything where i can just do a for loop and set 1 button each run through?

    for (i=0;i < 8; ++i){

    button[i].visible = true

    }

    anything like that? it'd be a huge help.

    I think it could be done using reflection, but using a container is the better way to do it. Cocincidentally, a Form is also a container for the controls it contains, so something along the lines of foobarForm.Controls["button"+i] might help.

     



  • PUT ME ON THE FRONT PAGE! :<FONT color=#0000ff size=2>
            Dim c As Windows.Forms.Control
            For Each c In Me.Controls
                z = z + 1
                If c.GetType.ToString.Contains("Button") Then
                    k(z) = z
                End If
            Next
            For y = 0 To k.Length
                If k(y) > 0 Then
                    Me.Controls.Item(k(y)).Visible = True
                End If
            Next</FONT>

    <FONT color=#0000ff>This is the best i can do, and VS deleted my project when i saved the .vb as a text file, so i'll do more later. (damn, and i had all the buttons working like they were supposed to, as well)</FONT>

    <FONT color=#0000ff>note: k(y) > 0 if there is a button there, re: the first for each loop. I forget index math, so this is probably a lot slower than it should be.</FONT>

    <FONT color=#0000ff>Oh and if i replace k() with another array that merely has the values put into k() i can have an array that has the index of all my buttons. what is reflection? is it easier than this?</FONT>

    <FONT color=#0000ff>i'm also wondering if i can have dim ctrl() as windows.form.control and just have the array of controls that i want to keep in there.<FONT size=2>

    </FONT></FONT>


  • Translation to VB.NET is left as an exercise for the reader.. oh, and I don't really know what you're trying to do:

    <FONT size=2> 

    </FONT><FONT color=#0000ff size=2>int</FONT><FONT size=2> z = </FONT><FONT color=#2b91af size=2>Convert</FONT><FONT size=2>.ToInt32(</FONT><FONT color=#2b91af size=2>Math</FONT><FONT size=2>.Round(</FONT><FONT color=#2b91af size=2>Convert</FONT><FONT size=2>.ToDouble(textBox1.Text)*1));

    </FONT><FONT color=#0000ff size=2>int</FONT><FONT size=2> counter = 0;

    </FONT><FONT color=#0000ff size=2>foreach</FONT><FONT size=2> (</FONT><FONT color=#2b91af size=2>Control</FONT><FONT size=2> c </FONT><FONT color=#0000ff size=2>in</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>this</FONT><FONT size=2>.Controls)

    {

    </FONT><FONT color=#0000ff size=2>if</FONT><FONT size=2> (c </FONT><FONT color=#0000ff size=2>is</FONT><FONT size=2> </FONT><FONT color=#2b91af size=2>Button</FONT><FONT size=2> && counter < z)

    {

    counter++;

    c.Visible = </FONT><FONT color=#0000ff size=2>true</FONT><FONT size=2>;

    }

    }

    </FONT>


  • @webzter said:

    Translation to VB.NET is left as an exercise for the reader.. oh, and I don't really know what you're trying to do:

    I want to know the index value of all controls that have "button" in their name. so that i can set them visible or invisible using a select case statement, or a for...next loop, or just arbitrarily.



  • Do you care that they have a button in their name or that they are a button?



  • Pretty simple example to set you off:

     

            For Each c As Control In Me.Controls
                If c.Name.Contains("Button") Then c.Text = "Use an OO language in an OO way"
            Next

     You're overcomplicating things by getting the index from the object and then using the index to try to get back to the object..

    As for the select/case in VB - it's different to the C way. Worse in some ways but better in others. That's part of being a different language.



  • If you need to do a "set every button after me in the list to visible, just create your own control array in your constructor adding in references to your buttons

     

            Dim Buttons(8) As Button
            x(1) = Me.Button1
            x(2) = Me.Button2
            ..........
     

     and work with them that way.



     



  • @webzter said:

    Do you care that they have a button in their name or that they are a button?

    I care that they are a button, and which button it is (there are 7 that i need to be able to set.visible max)

    I wish i could do it OO, but i am trying to figure out a way to not do

    someVar(1) = button1

    someVar(2) = button2

     I just wanna be able to iterate through the button ids (cause they're integers) and set them on or off depending on what i need.

    I was really hoping for some 4 line bit of code, since you'd think this is a pretty common task for updating a window when a user inputs something (substitute buttons for labels and i have another exampe)

    because what i'd really like to do is be able to have 1 "onclick" command for all the buttons that determines what button was pushed and sets my variable up appropriately.

    rather than having to copy and paste 7 button "onclick" segements.

     

    I suppose that's really what i am lookin for... the OO way to do it :-)



  • I think you're looking for "TypeOf" in VB.NET, e.g.

    For each c In Me.Controls
      If TypeOf c Is Button Then ...
    Next




  • You can use control collections to help group which buttons should be enabled. VB.NET definitely does do fall-through on switches, though. I'm guessing you're running into a typing problem. Have you tried a simpler example e.g.:

     
    Sub Test(Byval i as Integer)
    Select case i
       Case 0 to 5
         MsgBox("It's between 0 and 5")
       Case 6 to 10
         MsgBox("Between 6 and 10")
       Case Else
          MsgBox("Something else.")
       End Select
    End Sub

    Test(3)
    Test(8)

    ...works as expected for me in VB.NET. 



  • @GeneWitch said:

    this won't set both to visible... To which i put forth this question

    Let's say i have 8 cases that i want to fall through in order (like in C) starting at the least likely and ending at the most likely... is there any way to do this in VB.NET without If .. Else if?

    It's VisualBasic. You're supposed to use copy&paste. It creates the most beautiful code:

    <font size="2">y = Math.Round(TextBox1.Text.ToString * 1)</font>

    <font size="2"> </font>

    <font color="#0000ff" size="2">Select</font><font size="2"> </font><font color="#0000ff" size="2">Case</font><font color="#0000ff" size="2"> y

    Case</font><font size="2"> 0 </font><font color="#0000ff" size="2">To</font><font size="2"> 1

    Button1.Visible = </font><font color="#0000ff" size="2">True

    </font><font color="#0000ff" size="2">Case</font><font size="2"> 2 </font><font color="#0000ff" size="2">To</font><font size="2"> 3
    </font><font size="2">Button1.Visible = </font><font color="#0000ff" size="2">True

    </font><font size="2">
    Button2.Visible = </font><font color="#0000ff">True
    </font><font color="#0000ff" size="2">Case</font><font size="2"> 4 </font><font color="#0000ff" size="2">To</font><font size="2"> 5
    </font><font size="2">Button1.Visible = </font><font color="#0000ff" size="2">True

    </font><font size="2">
    Button2.Visible = </font><font color="#0000ff">True
    </font><font size="2">
    Button3.Visible = </font><font color="#0000ff">True
    </font><font color="#0000ff" size="2">Case</font><font size="2"> 6 </font><font color="#0000ff" size="2">To</font><font size="2"> 7
    </font><font size="2">Button1.Visible = </font><font color="#0000ff" size="2">True

    </font><font size="2">
    Button2.Visible = </font><font color="#0000ff">True
    </font><font size="2">
    Button3.Visible = </font><font color="#0000ff">True
    </font><font size="2">
    Button4.Visible = </font><font color="#0000ff">True
    </font><font color="#0000ff" size="2">Case</font><font size="2"> 8 </font><font color="#0000ff" size="2">To</font><font size="2"> 9
    </font><font size="2">Button1.Visible = </font><font color="#0000ff" size="2">True

    </font><font size="2">
    Button2.Visible = </font><font color="#0000ff">True
    </font><font size="2">
    Button3.Visible = </font><font color="#0000ff">True
    </font><font size="2">
    Button4.Visible = </font><font color="#0000ff">True
    </font><font size="2">
    Button5.Visible = </font><font color="#0000ff">True
    </font><font color="#0000ff" size="2">Case</font><font size="2"> 10 </font><font color="#0000ff" size="2">To</font><font size="2"> 11
    </font><font size="2">Button1.Visible = </font><font color="#0000ff" size="2">True

    </font><font size="2">
    Button2.Visible = </font><font color="#0000ff">True
    </font><font size="2">
    Button3.Visible = </font><font color="#0000ff">True
    </font><font size="2">
    Button4.Visible = </font><font color="#0000ff">True
    </font><font size="2">
    Button5.Visible = </font><font color="#0000ff">True
    </font><font size="2">
    Button6.Visible = </font><font color="#0000ff">True

    </font><font color="#0000ff">end select

    </font>

     

    (Sorry, can't help being a smartass) 



  • <FONT size=2>

    </FONT><FONT color=#0000ff size=2>private</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>void</FONT><FONT size=2> CreateButtons_Click(</FONT><FONT color=#0000ff size=2>object</FONT><FONT size=2> sender, </FONT><FONT color=#2b91af size=2>EventArgs</FONT><FONT size=2> e)

    {

    </FONT><FONT color=#0000ff size=2>int</FONT><FONT size=2> numberOfControlsToCreate = </FONT><FONT color=#2b91af size=2>Convert</FONT><FONT size=2>.ToInt32(NumberOfControlsTextBox.Text);

    </FONT><FONT color=#2b91af size=2>Control</FONT><FONT size=2>[] buttons = </FONT><FONT color=#0000ff size=2>new</FONT><FONT size=2> </FONT><FONT color=#2b91af size=2>Control</FONT><FONT size=2>[numberOfControlsToCreate];

    </FONT><FONT color=#0000ff size=2>for</FONT><FONT size=2> (</FONT><FONT color=#0000ff size=2>int</FONT><FONT size=2> i = 0; i < numberOfControlsToCreate; i++)

    {

    buttons[i] = </FONT><FONT color=#0000ff size=2>new</FONT><FONT size=2> </FONT><FONT color=#2b91af size=2>Button</FONT><FONT size=2>();

    buttons[i].Click += </FONT><FONT color=#0000ff size=2>new</FONT><FONT size=2> </FONT><FONT color=#2b91af size=2>EventHandler</FONT><FONT size=2>(buttonGroup_Click);

    buttons[i].Text = </FONT><FONT color=#a31515 size=2>"Button "</FONT><FONT size=2> + i;

    buttons[i].Tag = i;

    buttons[i].Top = i*30;

    </FONT><FONT color=#0000ff size=2>this</FONT><FONT size=2>.Controls.Add(buttons[i]);

    }

    }

    </FONT><FONT color=#0000ff size=2>private</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>void</FONT><FONT size=2> buttonGroup_Click(</FONT><FONT color=#0000ff size=2>object</FONT><FONT size=2> sender, </FONT><FONT color=#2b91af size=2>EventArgs</FONT><FONT size=2> e)

    {

    </FONT><FONT color=#2b91af size=2>MessageBox</FONT><FONT size=2>.Show(((</FONT><FONT color=#2b91af size=2>Button</FONT><FONT size=2>) sender).Tag.ToString());

    }

    </FONT><FONT color=#0000ff size=2>private</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>void</FONT><FONT size=2> ToggleButton_Click(</FONT><FONT color=#0000ff size=2>object</FONT><FONT size=2> sender, </FONT><FONT color=#2b91af size=2>EventArgs</FONT><FONT size=2> e)

    {

    </FONT><FONT color=#0000ff size=2>foreach</FONT><FONT size=2>(</FONT><FONT color=#2b91af size=2>Control</FONT><FONT size=2> c </FONT><FONT color=#0000ff size=2>in</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>this</FONT><FONT size=2>.Controls)

    {

    </FONT><FONT color=#0000ff size=2>if</FONT><FONT size=2>(c </FONT><FONT color=#0000ff size=2>is</FONT><FONT size=2> </FONT><FONT color=#2b91af size=2>Button</FONT><FONT size=2> && c.Tag != </FONT><FONT color=#0000ff size=2>null</FONT><FONT size=2>)

    {

    c.Visible = !c.Visible;

    }

    }

    }

    </FONT>


  • It's been years since I've done VB6... and never since I've done VB.net.... but surely to God you can create control arrays at design time like you used to in the ol' days.  If so, create 8 instances of the same button (named the same) on your form and you've got an array.

    In VB6, you'd do it like

    <FONT face="courier new,courier">For i = 0 To UBound(Button)
        Button(i).Visible = SomeFunctionThatReturnsABoolean(i)
    Next</FONT>



  • You can't do control arrays anymore.  You can access controls by name by using Me.Controls("Button" & ButtonID).Visible = True.



  • In GW-BASIC there was a statement that could be like a select case with fallthrough (small numeric values only though). The syntax was "ON var GOTO first,second,third..." It was present in both QBasic and VB 3.0 but apparently it's gone in VB.Net. Bastards.



  • @Goplat said:

    In GW-BASIC there was a statement that could be like a select case with fallthrough (small numeric values only though). The syntax was "ON var GOTO first,second,third..." It was present in both QBasic and VB 3.0 but apparently it's gone in VB.Net. Bastards.

    Other BASIC dialects even allowed for calculated gotos. (For those who don't know pre-VB BASIC: Lines had line numbers, which also served as targets for GOTO.)

    ON...GOTO is, like all kinds of GOTO, a relict of spagetti programming.
     



  • @GeneWitch said:

    @webzter said:

    Do you care that they have a button in their name or that they are a button?

    I care that they are a button, and which button it is (there are 7 that i need to be able to set.visible max)

    I wish i could do it OO, but i am trying to figure out a way to not do

    someVar(1) = button1

    someVar(2) = button2

     I just wanna be able to iterate through the button ids (cause they're integers) and set them on or off depending on what i need.

    I was really hoping for some 4 line bit of code, since you'd think this is a pretty common task for updating a window when a user inputs something (substitute buttons for labels and i have another exampe)

    because what i'd really like to do is be able to have 1 "onclick" command for all the buttons that determines what button was pushed and sets my variable up appropriately.

    rather than having to copy and paste 7 button "onclick" segements.

     

    I suppose that's really what i am lookin for... the OO way to do it :-)

    If you want one event handler for each of the buttons just interrogate the sender arg to determine the button clicked.

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _

            Button1.Click, Button2.Click, Button3.Click, Button4.Click, Button5.Click, Button6.Click, Button7.Click, Button8.Click

            Dim myButton As Button = DirectCast(sender, Button)

            MsgBox(myButton.Text)

       End Sub
     

     



  • @ammoQ i remember such things. :-(

    @lpope:

    Nice. that's exactly what i was looking for. :-)

    I'll have to play with it a bit to get it to do what i want, but that should work, thanks!



  • I don't have .NET on this machine, but it's very similar to Delphi. In Delphi, the Controls array has a FindComponent() method:

      TempButton := Self.Controls.FindComponent('Button1');

    If I have buttons named "Button1" through "Button10", I can iterate through them:

    for i := 1 to 10 do
    begin
        TempButton := Self.Controls.FindComponent('Button' + IntToStr(i));
        if TempButton <> nil then
          DoSomethingWithTheButton(TempButton);
    end;

    I don't recall exactly what it's called in .NET, but I know there's something similar there. 

     



  •  

    ...In Delphi, the Controls array has a FindComponent() method...

    The answer to this has already been posted.  The function in question is one of the overloads of the Item property of the forms controls collection.

    I dont know what logic the app is trying to apply but you can group controls together on panels then change the visible property of the panel instead of the individual controls.  Might mean you only need one line in each Case, you could also consider me.button1.visible=somevalue<1 instead of the select case approach.

    ...but surely to God you can create control arrays at design time like you used to in the ol' days...

    No thank god, control arrays where only a substitute for being able to attach event handlers at runtime to allow for runtime creating of controls.  They are nasty and I am not sure it is a good idea to try to emulate them.

    Also, thank god On x GOTO and ON x GOSUB have the calculated versions have gone.  Friend of mine did 'invent' a maybe worse system though.
    Present a numbered list of options to the user
    then run Eval("menu" + itemSelected)


Log in to reply