CanOz Blog

Neil Knobbe's Blog at vbCity

This blog hosted by:
http://blogs.vbcity.com      
  Home :: Syndication  :: Login

AprMay 2008Jun
SMTWTFS
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

Archives

Image Galleries

vbCity Blogs

Saturday, May 03, 2008 #

ClickOnce Deployment

A recent post on vbCity regarding deploying an application with ClickOnce got me wondering about doing deployment with ClickOnce.

I have always done deployment of applications by creating and using a Setup and Deployment package which created a .msi installer file, so it was interesting to see some of the differences between the two distribution methods.

First off I created a simple application to test the ClickOnce distribution and installation method with.  What I created was nothing special, just a windows form with at button that, when it is clicked, a message box is shown.

 

As you can see the application is nothing special.  One other thing that I did was add a version number to the text of the form.  I did this to show how ClickOnce deployment installs newer versions as they are available.  I will get to this a little later.

Once your application is ready to go you want to open up the My Project page from the solution explorer.

On the My Project  page click the Publish tab.

From this page, you define where your application is going to be available from and how it is going to be installed on the client machine.

Taking a look at the publish page from the top down the first thing you will want to enter will be the location (URL) that you are going to publish to.

As you can see from the image above, you have three options for the location that you are going to publish to.  You can publish to a web site (http://www.somesite.com) but to do this you must have FrontPage extensions enabled on the web site.  You can publish to a ftp server (ftp://www.somesite.com) as long as you have ftp permissions for the site, or you can publish to a local file (C:\myApplication). (For distribution this last option is not really that realistic unless you are on an internal network where you can share out the directory to others on the network.)

The next option you have is to determine if you application is available offline or not.

If you don’t want the users to be able to access your application offline then select the online option.  This will cause your application to run, but not show in the start menu of the user’s computer.  They would need to download the application each time they wanted to use your application. 

If you make the application available offline then a shortcut is included in the start menu of the computer making the application accessible all the time.

To the right of the Install settings there is a group of four buttons.

These buttons define what files are to be included with your application, any prerequisites that the end user must have installed on their computer to run your application, how and when to get updates as well as options such as adding the publishers name, product name etc.

Under the install mode and the buttons there is the version boxes plus the option to automatically increment the revision with each publish.

Keeping the increment box checked is, I believe, quite important.  If you don’t remember to increment the version number when you republish the application then the next time the application checks for updates it looks at the version number and if that number has not changed, even though your application may have, it assumes that there is nothing newer and opens the currently installed version.

The last two items on the window are the Publish Wizard and Publish Now buttons.

The Publish Wizard button will open a series of dialogues and walk you through the settings that you want your installer to use.

The Publish Now button will use the information that you have entered on the page and create the installer files then, if you are deploying the files to either a web site or ftp site, prompt you for log on details.

Simply insert your username and password then click the OK button and the files required will be uploaded to the URL you specified.

You can see in the image above that ClickOnce has created two files and one directory on the web server.  Within the Application Files directory you would find one directory containing each version that has been published and uploaded.

I just happen to have two versions in the application files directory and the one that will get distributed will always be the latest version. (I mentioned earlier that I had put a version number on the text of the form and the version number you should see is 2 not 1 like the image of the form above.) It would not matter how many older versions I have on my server.

Now you may distribute the address of your application to your clients.  The file that you want to point to is the Application Manifest file, not the setup file.  From the image above I would point people to the URL http://www.neilknobbe.com/clickonce/ClickOnce.application.  (The link is live and you can navigate to it, download and install the application that I mentioned at the start of this post.  It is not very exciting, but it shows how ClickOnce works.)

The prerequisites for installation, which you would have set earlier, are checked.

If all is ok, the user will be prompted to install the application.

Once installed your ClickOnce deployed application is ready to use.

posted @ 7:49 PM | Feedback (0)

Thursday, April 24, 2008 #

Ok, let’s call this page 22,492 in the book of things I did not know about Visual Studio 2005.

I was reading something the other day, if I can remember or find it I will post up a link, and was surprised that I had missed this little bit before. 

(I have recently been reading “WPF for those who know Windows Forms” that can be found here  and watching webcasts by William Steele on his WPF Soup To Nuts series so it could have could have come from one of those.)

What was mentioned was having both text and an image on a button.  I knew it was possible, but I didn’t know just how easy it was to do.

By default when you add an image to the button the text of the button is overlays the image.

There is a property of a button which helps us set the relation of the text to the image.  This name of this property is TextImageRelation.


The TextImageRelation property has five options:

  • Overlay
  • Image over text
  • Text over image
  • Image before text
  • Text before image

The options are pretty much self explanatory.  Below are screen shots showing the different positions.

Image over text:

Text over image:

Image before text:

and lastly

Text before image:

posted @ 7:17 PM | Feedback (0)

Tuesday, April 22, 2008 #

The companion video to my post on the expander control in WPF is now available for download.

The video can be found here.

posted @ 11:15 PM | Feedback (0)

Friday, April 18, 2008 #

I was taking another look at the WPF expander control that I talked about here and discovered that you don't actually need to use any code to get rid of the background colour of the control when collapsed.

What I discovered is that if you set the VerticalAlignment of the expander control.  You can set this property to Bottom, Center, Stretch and Top.  All but Stretch will hide the background colour of the control when the control is collapsed.

Here is the revised XAML markup for the control:

posted @ 2:09 AM | Feedback (0)

Thursday, April 17, 2008 #

A couple of days later than I had planned, but I finished the video that is the companion of this post about custom content in the tabs of a tab control in WPF.

You can download the video here.

posted @ 2:59 PM | Feedback (0)

Monday, April 14, 2008 #

After posting up about this feature   of Visual Studio I got to messing around with it a bit. (Sara Ford's post got me excited about this topic)

I got to thinking that although it was a great idea to be about to store code snippets in the toolbox, I did get to thinking that it could get confusing having all sorts of code for different things in one tab and be able to separate the code in organized groups would be handy.  Well guess what.  It can be done.

If you right click on the General tab of the toolbox you can select to add a tab.

A new tab is created and all you need to do is type in the name that you want your tab to have.

Now you can organize your code, and control, snippets so they are easy to find.

posted @ 2:24 AM | Feedback (0)

There are a lot of neat options now available to us programmers thanks to WPF.

One of these is the expander.  The expander is a control pretty much like a groupbox which can hold various controls.  The main difference between a groupbox and an expander is the controls in a groupbox are always visible where the expander gives the developer, and by extension the user, the ability to hide any controls and conserve valuable space on a windows form.

As you can see in the image below, the groupbox and expander both contain two radio buttons.

The advantage of the expander, as I see it, is when I click the little arrow next to the caption of the expander.  Once clicked the expander collapses to the height of its header hiding the controls, in this example the radio buttons, from view. 

I will admit that I had to do a little tinkering with the expander to get it looking and working like I wanted it. 

I dragged and expander from the toolbox onto my window, sized it and set the background colour, then added a stack panel, and within the stack panel, the two radio buttons.

 

This, unfortunately, was not quite what I wanted because the whole background of the expander was light blue and I only wanted the header to be blue with a small border around the controls.

To solve this I had to put a border on the expander before putting the stack panel and the radio buttons.  Setting the background colour of the border to white and adding a margin and padding for the border completed the look I was attempting.

Well it had the look as long as the expander was expanded.  Once I clicked the button to collapse the expander I was left with a blue square.

No radio buttons but not perfect either. 

To get the desired effect of a growing and shrinking panel I used the Expanded and Collapsed methods of the expander to set the height when expanded and collapsed.

Now I have the effect I was after.

Here is the XAML for the expander with the frame, stack panel and two radio buttons.

posted @ 2:08 AM | Feedback (3)

Sunday, April 13, 2008 #

Sara Ford blogged about this a couple of days ago and I thought it was a really cool feature of Visual Studio.

She pointed out, what could be, a little known feature of Visual Studio. 

You can highlight and then drag code snippets into the General tab of the toolbox.

You will then fine the code as an item in the toolbox.

If you want to see exactly what the code is all you need to do is hover your mouse over the item and the code will be displayed.

I think that this is one of the cooler features of Visual Studio and a great and easy way to keep code snippets.

posted @ 2:12 AM | Feedback (0)

Saturday, April 12, 2008 #

After having looked at how to change the background colour of the tab header I got to wondering what else can be done to the tabs using WPF.In a very short time my question changed from “What can be done?” to “What can’t be done?”

As was shown here by MVP Ged Mead you can easily set the background colour of the tabs on a tab control, and a solution to the setting the background of the header here. Those posts got me wondering just what else could be done with the tabs on a tab control.

With very little time and effort I ended up with a tab control that looked like the following.

As you can see the captions on the tabs are quite varied and although you can’t tell from the image the last tab is very different.  The first tab has text with mixed styles, the second tab has a rectangle included with the text and it looks like I have images on the last two tabs, but in fact the last tab has a video playing on it.  Yes, I did say video.  Complete with sound.

Believe it or not his whole tab control was created with just 33 lines of XAML markup.

So leveraging the power of WPF we can easily create much more visually stimulating tab controls than you could with previous versions of Visual Studio.


I’ll create a companion video for this and post it up in a couple of days which will also show the video on the fourth tab playing.

posted @ 4:10 PM | Feedback (2)

Sunday, April 06, 2008 #

This is a follow up on the post about changing the colour of the TabPanel part of the tab control. 

I created a video showing how I went about changing the template of the tab control using Expression Blend.

You can download the video to watch from here.

posted @ 8:04 PM | Feedback (0)

Saturday, April 05, 2008 #

A question came up in the vbCity Forums that I participate in about changing the background colour of the header portion of the TabControl.  The original question was about changing the colour of the tabs themselves (original question).

vbCity Leader (and Microsoft MVP) Ged Mead posted up code to change the colour of the tabs, but once the tab control's DrawMode property was set to “OwnerDrawFixed” the portion of the tab control without button changed to the default colour of “Button” which made it no longer the same as the background colour of the form. 

 

I recalled that Ged had posted up a WPF solution for the background colour of a tab previously and figured that with WPF it may well be possible to change the colour for the rest of the tab header also. 

So I forged ahead with my attempt to find a solution.  Not being in any way shape or form a pro with WPF, I decided to try modifying the tab control with Expression Blend instead of Visual Studio.  After a little messing around I did find that you can set the background colour of a tab control header to whatever colour you want and still have the tabs themselves with different colours. 

I started out by taking the XAML that Ged posted and pasted that into my Expression Blend project as a starting point so it looked like the following.  ( I did have to remove the image from the 3rd tab as I didn't have that particular image on my computer.) 

Then I went in and began to look at editing the template of the tab control itself. 

With very little fuss, I was able to set the background property of the TabPanel (this is the part of the tab control which holds the tab buttons) and I ended up with a coloured header background.

To accomplish this change you can either edit the XAML of the tab control, if you know what you are doing with XAML, and add in markup for the tab panel of the tab control and include a color for the background attribute.

or you can, as I did, right click on the tab conrol and from the popup menu “edit control parts (template)”.  Moving your mouse over “edit control parts (template)” causes a submenu to become visible and you then select “edit a copy”.  The Create Style Resource window opens and you are faced with a few choices.  I decided to keep the default choices (resource name and define in this document) just for ease.  Click the “OK” button and you are ready to start making changes to the template.

Since all I wanted to do was change the background of the tab panel, I selected it by clicking on the part of the tab panel that didn't have any buttons and in the properties pane I set the background to the colour that I wanted.  That is how easy it was to get the effect that was required. 

Once I had made all the changes required, I simply copied the XAML of the tab control from Expression and pasted it into a Visual Studio project and was ready to continue.

Below is the complete XAML for the tab control as shown above.

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns
:x="http://schemas.microsoft.com/winfx/2006/xaml"
x
:Class="Window1"
x
:Name="Window"
Title
="Window1"
Width
="640" Height="480">


<Window.Resources>
<SolidColorBrush x:Key="TabControlNormalBorderBrush" Color="#8C8E94"/>
<
Style x:Key="TabControlStyle1" TargetType="{x:Type TabControl}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<
Setter Property="Padding" Value="4,4,4,4"/>
<
Setter Property="BorderThickness" Value="1"/>
<
Setter Property="BorderBrush" Value="{StaticResource TabControlNormalBorderBrush}"/>
<
Setter Property="Background" Value="#F9F9F9"/>
<
Setter Property="HorizontalContentAlignment" Value="Center"/>
<
Setter Property="VerticalContentAlignment" Value="Center"/>
<
Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="ColumnDefinition0"/>
<
ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
Grid.ColumnDefinitions>
<
Grid.RowDefinitions>
<RowDefinition x:Name="RowDefinition0" Height="Auto"/>
<
RowDefinition x:Name="RowDefinition1" Height="*"/>
Grid.RowDefinitions>
<
TabPanel Margin="2,2,0,0" x:Name="HeaderPanel" Grid.Column="0" Grid.Row="0" Background="#FF0968BA" IsItemsHost="true" Panel.ZIndex="1" KeyboardNavigation.TabIndex="1"/>
<
Border x:Name="ContentPanel" Grid.Column="0" Grid.Row="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="{TemplateBinding Padding}" x:Name="PART_SelectedContentHost" ContentSource="SelectedContent"/>
Border>
Grid>
<
ControlTemplate.Triggers>
<Trigger Property="TabStripPlacement" Value="Bottom">
<Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
<
Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
<
Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<
Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
<
Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/>
Trigger>
<
Trigger Property="TabStripPlacement" Value="Left">
<Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
<
Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
<
Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
<
Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
<
Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
<
Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
<
Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<
Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
<
Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/>
Trigger>
<
Trigger Property="TabStripPlacement" Value="Right">
<Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
<
Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
<
Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
<
Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
<
Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
<
Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
<
Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<
Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
<
Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/>
Trigger>
<
Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
Trigger>
ControlTemplate.Triggers>
ControlTemplate>
Setter.Value>
Setter>
Style>
Window.Resources>
<TabControl Margin="8" Name="TabControl1" Style="{DynamicResource TabControlStyle1}">
<TabItem Header="Members" Background="LightGreen"
   Foreground="Navy">
<Grid>
<ListBox Width="150" Background="LightGreen"
   HorizontalAlignment="Left">
<ListBoxItem>J SmithListBoxItem>
<
ListBoxItem>J JonesListBoxItem>
<
ListBoxItem>C B TravisListBoxItem>
<
ListBoxItem>L FourleatherListBoxItem>
ListBox>
Grid>
TabItem>
<TabItem Background="Green" Header="Associates"
   Foreground="Navy" >
TabItem>
<TabItem Background="LightBlue">
<TabItem.Header>
<StackPanel Orientation="Horizontal" >
<Image Width="20" />
<
TextBlock Text="   Sponsors" Foreground="Red"/>
StackPanel>
TabItem.Header>
<Grid>
<ListBox>
<ListBoxItem>J SmithListBoxItem>
<
ListBoxItem>J JonesListBoxItem>
<
ListBoxItem>C B TravisListBoxItem>
<
ListBoxItem>L FourleatherListBoxItem>
ListBox>
Grid>
TabItem>
TabControl>
Window>

posted @ 6:48 PM | Feedback (0)

Saturday, March 15, 2008 #

I was taking a look at working with a WPF application the other day when I found, what I thought, was a really neat feature of Visual Studio 2008.

What I came across was the “Search” feature that is built into the Properties window of my WPF application.  It was quite by accident that I found the search ability because I could not find the property of a control that I was trying to change.  I knew the property existed, but for the life of me I could not find it. 

If your display is like mine, when I look at the property window in Visual Studio, there are more properties than can be shown on the screen so the scroll out of sight.

Getting to a property, or finding the property as was my case, is much easier if you make use of the property windows search feature.

As you type in the search box, Visual Studio filters the properties of the Control to show only the properties that contain the letter(s) that you enter into the search box.

So if, for example, you want to quickly find the width property. When you type “w” into the search box, the list of properties is narrowed down.

Add an “i” into the search box and the list is filtered even more,

and so on if you want to keep going and type in the whole name of the property.

While this may not always be the quickest way to find a property, I thought it was a nifty addition to Visual Studio 2008.

posted @ 6:29 PM | Feedback (0)

Monday, November 28, 2005 #

In the previous post I talked about Reading Files.  Now I will show you how to Write Files.

 

Writing to Files is as easy as Reading from Files.  As with Reading Files you need to Import the System.IO Namespace.

 

Imports System.IO

 

As with the StreamReader, writing with StreamWriter can be done in more than one way.  How you Write to the File will also depend on if you want to Write to a New File, Overwrite and existing File or Appending and existing File.

 

Let’s take a look at Writing to a New File.

 

Dim sw As New StreamWriter(PathToFileHere)  ' Declare your StreamWriter and File Path

Dim MyString As String  ' Declare the String you will write to the File

 

MyString = “Blah, Blah, Blah”  ' Set the Value of your String

 

sw.Write(MyString)  ' Write the String to the File

 

sw.Close()  ' Close the StreamWriter

 

The above code will create the File, if it does not Exist and write the String to the File.  (*Caution is advised here as the same code will Overwrite the contents of an existing File.)

 

If you want to Append an Existing File there are a couple of ways to go about it.  As always when working with files you need to add the Imports Statement.

 

Imports System.IO

 

Then you need to add the code that will Append the File.

 

Dim sw As StreamWriter = File.AppendText(PathToFileHere)

Dim MyString As String

 

MyString = “Blah, Blah, Blah”

 

sw.Write(Environment.NewLine & MyString)

 

sw.Close()

 

You can also use WriteLine()

 

Imports Sytsem.IO

 

Dim sw As New StreamWriter(PathToFileHere)

Dim MyString As String

 

MyString = “Blah, Blah, Blah”

 

sw.WriteLine(Environment.NewLine & MyString)

 

sw.Close()

 

Hopefully this quick look at Writing to Files gives you a start on Writing Files.

posted @ 7:48 PM

Depending on your Project you could find yourself needing to read Files.  One way that you can accomplish this is to use the StreamReader.  StreamReader is part of the System.IO Namespace and you must add the Imports Statement to your Project before you can access the StreamReader.  At the very top of your Form.vb code page, before anything else, you would type:

 

Imports System.IO

 

Now your Project can access the System.IO Namespace.  (Admittedly you could access the System.IO Namespace without using the Imports Statement.  You would just need to put System.IO in front of all the Classes of the IO Namespace that you use in your Project.  For example System.IO.StreamReader or System.IO.File.OpenText, but I prefer using the Imports Statement.)

 

The next thing you want to do is to declare your StreamReader.  A couple different ways of doing this are:

 

Dim sr As New StreamReader(PathToFileHere)

 

' or

 

Dim sr As StreamReader

sr = File.OpenText(PathToFileHere)

 

Depending on what you want to do with the contents of the File, you can Read the contents of the File Line by Line or the entire Length of the File.

 

Read entire Length of a File

 

Imports System.IO  ' Add Imports Statement to top of Form Code

 

Dim sr As New StreamReader(PathToFileHere)  ' Declare the StreamReader and Open the File

 

Dim MyString As String  ' Declare a String Variable to hold the contents of the File.

 

MyString = sr.ReadToEnd()  ' Read the contents of the file into the String Varaible

 

txtTextBox1.Text = MyString  ' Display the contents of the File.

 

Read a File Line by Line

 

Imports System.IO  ' Add Imports Statement to top of Form Code

 

Dim sr As StreamReader  ' Declare the StreamReader

 

sr = File.OpenText(PathToFileHere)  ' Open the File

 

Do While sr.Peek <> -1  ' While Peek can read Characters from the File (Peek Returns the next Character until there are no more then will Return a -1).

    sr.ReadLine() ' Read the next Line of the File

    txtTextBox1.Text &= sr.ReadLine & Environment.NewLine ' Display the Line of the File

Loop

 

sr.Close()

 

As with just about everything in programming there are several different ways to accomplish a task.  These are just two ways that you can go about reading the contents of Files.
posted @ 7:43 PM

Saturday, November 26, 2005 #

Looping through Controls

 

One of the things that I seem to find myself needing to do with each App that I write is at some point in time I will want to Loop trough the Controls on one of my Forms. 

 

There are plenty of ways of doing this and this is how I ended up going about it.

 

Chances are when you want to do this you will want to Loop through just one Type of Control to make sure that a certain condition is matched.  Let’s say, for instance, that we want to make sure that the User has entered something into all the TextBoxes on a Form. 

 

Coming from a VB6 background I started out thinking that this should not be too hard a thing to do.  So I tried the following code in a Test App.

 

Private Sub cmdButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdButton1.Click

    Dim MyControl As Control ' Decalre Variable to hold the Controls on the Form

    For Each MyControl In Me.Controls  ' Loop through the Controls on the Form

        If TypeOf MyControl Is TextBox Then  ' If the Control is a TextBox

            If MyControl.Text = "" Then  ' If there is no Text in the TextBox

                MessageBox.Show("You can not have an empty Textbox." _

                Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)

                Exit Sub  ' Exit the Sub

            End If

        End If

    Next

End Sub

 

When I ran the Text App, putting Text in some of the Textboxs and left others blank, and clicked the Button I got the Message Box as I should have.  I entered Text in all the TextBoxes, clicked the Button and was rewarded with no Message Box.  Great I thought, works like a charm. 

 

I opened up my real App and popped the code in the appripriate place and ran the App.  All worked well until it got to checking the TextBoxes.  The code only worked on some of the TextBoxes not all of them.  Something was wrong, but what.  I realized that the TextBoxes that were not being cleared were in a Panel so I had to do a little more research. 

 

What I needed to do was come up with something that would drill down a little further and take into account the fact that some Controls may be Containers for other Controls.  After a little bit of research I found the HasChildren Property of Control.

 

Armed with my new found knowledge, I set forth once again to my test project and added a couple of Frames to my Form and put a couple of TextBoxes into each Frame.  I knew that I once I got the clearing of Controls worked out I would want to use it in several places in my Project so I also decided that I needed to make the code reusable, so I decided to put the code in a Sub and call it when I wanted.

 

Private Sub ClearTextBoxes(ByVal cc As Control)

        Dim ctl As Control ' Declare Variable for the Controls on the Form

 

        For Each ctl In cc.Controls ' Loop through the Controls on the Form

            If ctl.HasChildren Then ' If the Control is a Container with Controls

                ClearTextBoxes(ctl) ' Call the Sub and Loop through all the Controls in the Container

            End If

            If TypeOf ctl Is TextBox Then

                If ctl.Text = "" Then  ' If there is no Text in the TextBox

                MessageBox.Show("You can not have an empty Textbox." _

                Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)

                Exit Sub  ' Exit the Sub

                End If

            End If

        Next

End Sub

 

Now I can just call the Sub and pass the Name of the Control that I want to Loop through the Controls of.  (In my Project I use this to Loop through Controls on one Tab of a TabControl.)

 

Private Sub cmdButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdButton1.Click

    ClearTextBoxes(TabControl1.TabPages(0)) '  Call the Sub and pass the Parameter.

End Sub

 

In the example above, the Parameter of the ClearTextBoxes Sub refers to the first Tab on the TabControl on the Form.  You can put the name of any Control, or your Form using the Me Keyword, and the Sub will only Loop through the Controls in the Container.
posted @ 11:34 PM