Class-level Static Variable per Instance - vb.net

I'm trying to do the following:
I need a static variable to get a ListItemCollection from a List control (I can do this, but if I don't set it as Shared It's not preserving the values as it should). The thing is that this class is a SharePoint webpart, so I most probably will be using the webpart more than once, and I need this variable to be unique to each webpart, which shared doesn't accomplish.
I tried everything you can imagine. I placed a Static variable within a Sub (shared and not shared), I tried it with Properties (also Shared and not shared)...
Any Ideas are welcome.
Thanks.

By definition, static members are per-class (or per-thread with a ThreadStatic attribute).

If you need to save the property on the webpart, add the WebPartStorageAttribute on the property, also throw on a FriendlyNameAttribute on there to make it clean:
C# Version:
[FriendlyNameAttribute("What the setting will be called")]
[WebPartStorage(Storage.Shared)]
private string MyStringThatGetsSaved { get; set; }
VB.Net Version:
<WebPartStorage(Storage.Personal), FriendlyNameAttribute("What the setting will be called")>
Private mMyStringThatGetsSaved As String
Public Property MyStringThatGetsSaved () As String
Get
Return mMyStringThatGetsSaved
End Get
Set(ByVal Value As String)
mMyStringThatGetsSaved = Value
End Set
End Property
Is this what you're after? If not can you clarify a bit further?

I finally went on another way, I just added some checkboxes to the toolpart and setted the properties on the webpart.
Anyway, what I was trying to do is:
Have a Web Part that changes its controls on Edit & Browse mode. In Edit mode I show two ListBox controls, two buttons (add, remove). When I click the add button, the value has to be removed from the left ListBox and be added to the right ListBox, so far so good I was able to make this functionality with no problems... The thing is when I go back to Browse mode I need to use the items in the ListBox from the right to show (so I added a ListItemCollection control that would store the values from the ListBox on the right), the text of the item and a TextBox control, then the user would enter their text in that textbox and hit the "Search" button and a search query would be executed.
My problem is that when I go from Edit to Browse the ListItemCollection variable I added is getting restarted. So I declared it as Shared, and that does work, but when I add a new instance of the WebPart, they have the same fields displayed... I don't know if there is a way of doing a Static Class-Level variable that is unique to each instance, so I went the ToolPart way...

Related

How to change the image displayed on a button at runtime in Visual Basic?

I am trying to change the Image attribute associated with a button when the button is clicked.
I have added the image I want to display (called "Black Pawn.png") as a resource within the solution and (from searching around and looking at similar questions) am trying to set the image attribute to it as shown below:
Private Sub boardButtonA2_Click(sender As Object, e As EventArgs) Handles boardButtonA2.Click
Dim sprites As Object = My.Resources.ResourceManager
boardButtonA2.Image = sprites.GetObject("Black Pawn.png")
End Sub
But when I click the button, the default image on it just disappears and is replaced with nothing instead of Black Pawn.png.
I am pretty new to using Visual Basic and Visual Studio so I may have failed to have added the image as a resource properly but I can see the image in the Solution Explorer above the form the button is in.
Any help or advice would be a great help.
Thanks.
EDIT:
Having thought more about the potential scenario, I'm wondering whether this answer is actually relevant. Your example code uses a hard-coded String but I'm wondering whether the actual String really would be a user selection. I'll leave it here anyway.
ORIGINAL:
There's no reason to use a hard-coded String to get a resource. If the String was from user entry then maybe, depending on the circumstances. As it is though, you should be using the dedicated property for that resource. That means using this:
boardButtonA2.Image = My.Resources.Black_Pawn
Just be aware that a new object is created every time you get a resource from My.Resources. For that reason, don't keep getting the same property over and over. If you need to use a resource multiple times, get it once and assign it to a field, then use that field multiple times, e.g.
Private blackPawnImage As Image
Private Function GetBlackPawnImage() As Image
If blackPawnImage Is Nothing Then
blackPawnImage = My.Resources.Black_Pawn
End If
Return blackPawnImage
End Function
and then:
boardButtonA2.Image = GetBlackPawnImage()
Also, I suggest that you change the name of the property to BlackPawn rather than Black_Pawn. You can change it to whatever you want on the Resources page of the project properties.
EDIT:
If this application is a chess game then you definitely will need every resource image for the playing pieces so you probably ought to get all of them at load and assign them to variables, then use them from those variables over the course of the game.
(I am assuming the question is for WinForms, if it isn't I will remove this answer)
When adding images as resources to a project, you have to pay attention to the name given to the resource after it is imported - the name can be changed if you want.
The image below is from one of my projects:
The name of the files on disk are:
CSV - Excel.png
GreenDot.png
RedDot.png
To fix your problem change the line:
boardButtonA2.Image = sprites.GetObject("Black Pawn.png")
to be:
boardButtonA2.Image = sprites.GetObject("Black_Pawn")
I don't think adding the image by going into Project > Add Existing Item properly added the image as a resource.
I instead went into *Project > (Solution Name) Properties > Resources > Images > Add Existing Item * and added it that way and was then able to get it working using jmcilhinney's method (I think my original method/a variation of it would work too but theirs is better).

Is there a way to pass values between forms in vb.net? (Without using a public variable)

I have an application that uses a second form with textBox and button, and i need to pass the text from textBox to the first form. I know how to do it with a public variable, but i would like to know if there is another way to do it without using a public variable.
Yes!
If the forms are part of the same solution, you simply write:
Dim MyVal1 As Integer = Form2.MyVal
MyVal1 exists in whatever form you write it in, and MyVal2 comes from Form2. These variables can only be shared if the forms have the right privacy settings.
If the two forms are part of separate applications, the only way i know of passing variables around is through constructors.
EDIT:
In your case with a textbox, you may be able to apply similar a solution:
Dim val As String = Form2.TextBox1.Text
You can use PUBLIC properties on the second form to read/write info to the other form.
You can overload the NEW method to pass variable during declaration.
You can create a public sub/function on the second form and pass variable byval or byref.
But, I would NEVER use a public variable. That is bad programming.

Add Property to Properties Window

I have built a UserControl class and am exposing certain properties to the parent object.
When i drag and drop the component to the parent objects designer surface, i get the effect i need (per say). What i want to further develop is the ability to pre-fill the property value (in properties window) as a default but it isnt auto-populating as i would have expected.
Here is what i have so far:
<Browsable(True), Category("Data"),
DefaultValue("01/01/1990")>
Public Property [Date] As String
Get
Return Me._dt
End Get
Set(value As String)
Me._dt = value
dtValue.Text = value
End Set
End Property
I understand that DefaultValueAttribute assigns the value if no other assignments are made, but thought it would also place that value in the field in the Properties Window.
As well, this ultimate assignment will go up one more level as a collection, so any advise or URL's for how to make a Collection of Components available via Properties Window?
I understand that DefaultValueAttribute assigns the value if no other assignments are made
That is incorrect.
The DefaultValueAttribute is just metadata that tells the designer what the default is.
It is still up to your code to ensure that the property actually gets that value.

Reading 'Checked' Property Of Dynamic CheckBox on Page Postback

Apologies in advance for the long-winded post, but I'm having some trouble with a .NET page I'm building.
END QUESTION: How can I check the 'Checked' property of a dynamically-created checkbox during the Page_Load subroutine?
DETAILS: Basically, I have a VB.NET page that creates some table rows dynamically, based on a number selected by the user. So, for example, if the user selects "3" from a dropdown list, the page posts back and creates three table rows. Each row contains a couple of textboxes, a dropdown list, and a checkbox (which are all .NET form controls rather than plain HTML controls, I should point out).
Typically, the user would enter a few details into the form controls, and click the 'Submit' button, after which the page iterates through each row, and inserts the data into a SQL Server table.
But if the user ticks the checkbox for that row, this signifies that the page is to ignore that row, and NOT insert that row of data into the database when the user clicks 'Submit'.
This works well, but there is a problem. If the user clicks 'Submit' and some of the values entered into the form controls are invalid (so, for example, the user didn't enter their name) then the page won't submit the data, and instead, shows an error to the user informing them of the values they need to change. But if the user creates three rows, for example, but decides to "ignore" the third row (by ticking the checkbox) then when the page posts back, finds some invalid entries, and re-shows the form to the user to allow them to correct any errors, I'd rather the page didn't render the third row altogether. After all, they chose to create three rows originally, but then decided that they only needed two. So it makes sense that the third row is not recreated.
To start with, I simply used code similar to the following within my Page_Load subroutine:
If objCheckbox.Checked = False
' Render the row, and recreate the dynamic controls '
Else
' Dont render the row or any of the controls '
End If
But what seemed to happen was that objCheckbox.Checked was always returning False, even when the checkbox was ticked. Once the page had loaded, the table rows had rendered again, and the tick was present in the checkbox, so it's not like the value was lost on postback. But at the point I check whether the checkbox is ticked, it always returns False, rendering a table row that the user doesn't need.
Does anyone know how to get round this problem? I've read lots of articles about the .NET ViewState, and the page lifecycle, but I've yet to find a solution that works. I simply need to be able to check if a checkbox is ticked before re-creating some dynamic controls.
I tried this alternative code, which utilises the ViewState, but to no avail:
If objIgnoreCheckbox.ViewState("Checked") = False Then
' Render the row, and recreate the dynamic controls '
Else
' Dont render the row or any of the controls '
End If
When doing this, I get the following error:
'System.Web.UI.Control.Protected Overridable ReadOnly Property ViewState() As System.Web.UI.StateBag' is not accessible in this context because it is 'Protected'.
So I tried to create a custom class, that inherited from Checkbox, and tried to override the ViewState property to make it public, so that it can be read from:
Public Class CheckboxControl
' Inherits all Checkbox properties and methods '
Inherits Checkbox
' Create the public ViewState property '
Public Overrides ReadOnly Property ViewState As StateBag
Get
Dim objChecked As Object = ViewState("Checked")
If Not (IsNothing(objChecked)) Then
Return objChecked
End If
End Get
End Property
End Class
But then I basically found out that you can't override a protected member with a public one. I've had very little experience with creating new classes etc, so I'm stumped.
So if anyone can tell me how to go about checking the darned checkbox, I'd be eternally grateful! I've spent a full working day trying to solve the problem, but with no luck!
Thanks in advance!
For static controls, the view state of controls is restored in Page_Init, which happens before Page_Load, so they contain the correct values in Page_Load. Dynamic controls are created in Page_Load, so their viewstate is incorrect in Page_Load and will be restored after Page_Load, but before calling event handlers. MSDN says:
After the Page_Load event has run, but before control event-handling methods are called, the remaining view state information is loaded into the dynamically created controls.
This is why Checked returns false, and why changing the visibility of CheckBox.ViewState will not solve your problem.
Solution (untested, but I think it should work): Create all controls (even those that you don't want to display) in Page_Load. Attach an event handler on CheckedChanged to your CheckBoxes (in Page_Load). After Page_Load has finished, ASP.NET will restore the view state of the newly created controls (that's why it is important to create the same controls in Page_Load, so that ASP.NET can correctly map the view state to the control), and ASP.NET will call your event handler for those CheckBoxes that have been changed. There, you can remove the rows you don't want to display.
This is how you add the event handler
AddHandler objCheckbox.CheckedChanged, AddressOf MyCheckedChangedFunction
This function would look something like this:
Function MyCheckedChangedFunction(sender As Object, e As EventArgs)
Dim objCheckbox = DirectCast(sender, CheckBox)
... access objCheckbox.Changed and do something useful here ...
End Function

Taking information from one window and putting it into another

I am developing a game and I want an options window to be used so that the user enters data into this and it carries to the main window instead of being lost...
I tried it with my recent program , guess the color , but it did not work the way I thought. I thought that I could assign it to a string in a textbox to a variable and it would carry into the main window...
I want this to happen:
The user begins the program by clicking shortcut
User clicks options in the toolbar
A new window comes onto the screen
In this window the user will select a map size then click ok the verify , radiobuttons used in this example...
Back to the main screen after clicking ok
User clicks new on toolbar to begin game
Game is then playing...
Edit:
Form1 <<< Form 2
game screen 3x3 button
end turn
Form 1
New game is begun
form 2 appears
3x3 button is pressed*
variable is used to change map (there is only one map for now)*
form2 closes and form1 shows
End turn is clicked
Generally, what you have to do is when you create a new form/window, you hold onto the reference of that form window until it closes.
Then, when it closes, you can copy the information back from the form/window that just closed into your main window (or whatever else you wish).
The key here is to expose properties on the child window which represent the inputs. So if the child window that was opened has a color that was selected, create a property which exposes that color so that the parent window can access it on the child.
EDIT: Why did I think this was a VB6 question? Did this get re-tagged? If the OP can clarify which version of VB, I'll update my example.
OOP even applies to VB6. Create an class to hold the shared data. At the application startup, create the object as a global object (variable). I hate global variables as much as the next guy, but in the case where this data needs to be seen by the whole application (a logged-in user object or a logging object, for example), it's appropriate. You can assign the values to the class object in the first form, and then read them from the class object in the second or any other form.
Example class:
Option Explicit
Private m_firstName As String
Private m_lastName As String
Public Property Get FirstName() As String
FirstName = m_firstName
End Property
Public Property Let FirstName(ByVal value As String)
m_firstName = value
End Property
Public Property Get LastName() As String
LastName = m_lastName
End Property
Public Property Let LastName(ByVal value As String)
m_lastName = value
End Property
Public Function FullName() As String
FullName = m_firstName & " " & m_lastName
End Function
I don't have VB6 on this machine, or I could have given you a better example. I think in .NET these days ;)
This may explain things quite a bit more - http://www.vbforums.com/showthread.php?t=374132