Property Default Value does not work for a new control - vb.net

I have a custom user control which expands and collapses. I have to have a second "open width" property that has to be set separately from the normal width property.
When I collapse the control, it makes the width 10. When I expand the control, it returns the control width back to the "open width" property, which has to be manually set to the normal width when the control is created.
The default new width on the control is 200, so for consistency I want to set the default "open width" property to 200 as well. So I have the following:
Private _mSideBarOpenWidth As Integer
<EditorBrowsable(EditorBrowsableState.Always)>
<Browsable(True)>
<DesignerSerializationVisibility( _
DesignerSerializationVisibility.Visible)>
<DefaultValue(200)>
<Category("SideBar")>
<Description("Sets the open Width of the SideBar control.")>
Public Property SideBarOpenWidth() As Integer
Get
Return _mSideBarOpenWidth
End Get
Set(value As Integer)
_mSideBarOpenWidth = value
End Set
End Property
When I drag a new control onto the form the default value is always 0. If I change it the value does persist, it just will not start at 200. I have done quite a bit of searching on this issue and I have tried the following:
cleaning/building/rebuilding the project
closing VisualStudio and opening it back up
deleting the form and creating a new one
using the control in a new project
setting <em>DesignerSerializationVisibility.Visible</em> to <em>.Content</em>
using <em>"200"</em> with the quotes as the default value
And various combinations of all those. None of that works and the default value on a new control dragged onto the form goes to zero. Needless to say I am at a loss on why the default value will not get set to 200 when it is created.
The only time I am even accessing the property is when I am setting the width of the control Me.Width = SideBarOpenWidth

it just will not start at 200
That is not what DefaultValue does. VS uses the DefaultValue to determine whether or not the current value differs from the default and so, should be serialized and show the property value in Bold in the Property IDE. It doesn't set the value. A remark from MSDN:
A DefaultValueAttribute will not cause a member to be automatically initialized with the attribute's value. You must set the initial value in your code.
Attributes provide information about a class, property etc. Your property doesnt know about the DefaultValue attribute and they don't interact without code you add.
Instead, they specify information about the class or property (etc) to other things (designers, serializers etc). For instance, which Editor or TypeConverter to use. A good example is the Description or Category attributes - these provide information about your properties to VS which it uses in the Properties pane in the IDE.

Related

Setting field of Access table using VBA from form

I'm trying to set a value of a field from a subroutine which I'm calling from an event handler. I'm simply doing width = 5
However, the field value isn't changed. However I can do height = 5 and the field value is set as expected. The field value for width remains unchanged at 12186.
I've tried changing the field name to image_width to no avail.
The form has neither controls height nor width.
What am I doing wrong / why is this one field not changing. I've tried deleting the field and recreating, and I don't see anything on this field that limits the setting of data.
Every form has an inbuilt property .Width so you can't use that for a field name.
A form doesn't have .Height, since this is a property of the form sections.
image_width shold work, though. Are you sure you edited all relevant settings?
i.e. Table field name, form field Name, form field Controlsource, VBA code?

Custom property not being set in code-behind

I have a boolean custom property. The property changes the behavior of the Form, and needs to be executed for intended behavior. However, if the property is False, it's not being set in the auto-generated code-behind (since the default value is False, the code-behind generator must think it's not necessary to set it). It seems that if I set the attribute on the property: [DefaultValue(True)] it will generate code-behind saying MyProperty = False, but then it won't do it for True property values. I wish to find a way for the property to always be set in code-behind, no matter what the property's value.
It seems my only alternatives are adding in Sub New()
Me.MyProperty = Me.MyProperty
Or else turning the property into an enum, which I don't like either.
It seems that the DefaultValueAttribute controls for which values something will be generated and set in code-behind, but I can't figure out a way to make it always generate code-behind. I was hoping setting an invalid DefaultValueAttribute would, but that just seems to make the designer use the last value.

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.

Can't escape empty textbox

I'm trying to track down the cause of an annoying interface bug in an app that was recently upgraded from VS2003 to VS2008 (the bug did not exist pre-migration).
What happens is this :
1) User clicks in textbox containing a date.
2) User clears date
3) User tries to move to another field, but can't. No error messages appear - it's as if the validation failed.
Further info :
1) The textbox's Text property is bound to a dataview which uses a datatable as its source. The bound field is a nullable datetime field with no constraints or default.
2) The Validating event fires and the CancelEventArgs property is not set to Cancel. The Validated, LostFocus and Leave events all fire as well, going LostFocus > Leave > Validating
3) I can't see any code changes relating to the control or the datasource with a couple of exceptions. The first is that this :
Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd"))
has now changed to this :
Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd", True))
The second is that this :
Me.dcolRangeEnd.DataType = GetType(System.DateTime)
has now changed to this :
Me.dcolRangeEnd.DataType = GetType(Date)
There is also this, which has been in the code since day one :
AddHandler txtRangeEnd.DataBindings("Text").Format, AddressOf FormatBoxToDate
Private Sub FormatBoxToDate(ByVal sender As Object, ByVal e As ConvertEventArgs)
Try
If Not e.Value Is DBNull.Value Then
e.Value = Format(e.Value, "d")
End If
End Try
End Sub
Now, if I remove the ", True" from the adding of the databinding then I can exit the control with a blank value, but it then reverts to the original value. Removing the date formatting appears to make no difference to this (it just reverts to showing 06/01/2011 00:00:00 rather than the desired 06/01/2010). No other code refers to that textbox at all. I'm thinking something must have changed in validation of databound controls between VS2003 and VS2008, but it's just as likely I'm missing something mind-numbingly obvious.
Any ideas?
The reason that you're seeing the observed behaviour is to do with how Windows Forms and it's Data Binding handles NULL database values.
The TL;DR reason:
See this Microsoft Connect suggestion: Provide better databinding support for nullable types
The long version:
What is essentially happening is that as you clear the Textbox (to an empty string) and subsequently tab away, the binding is converting your empty string to a DBNull value which is then propagated to the data source however the binding, since it is two-way, then attempts to re-populate the bound control (the Textbox) with appropriate formatting, and fails, causing the Textbox to display the strange behaviour of not allowing the focus to be removed from it!
This is happening due to the DataSourceNullValue property of the Binding class. This can be set using one of the Binding classes constructor overloads, or set separately via a property setting, however, if you do not explicitly set this property, it is important to note that:
The default is DBNull for value types
and null for non-value types.
It appears that you're not explicitly setting this, so the default is applying, and with your DateTime being a value type, it is using DBNull.
Once the data source has been updated (to DBNull), the binding mechanism will attempt to then repopulate the Textbox with the newly updated data source value. When the underlying data source value is DBNull, the value used for the bound control is governed by the Binding class's NullValue property. Again, if this property is not explicitly set either via the relevant overloaded constructor argument or via the property setting itself, the default value will apply, which is:
The Object to be set as the control
property when the data source contains
a DBNull value. The default is null.
Of course, a Textbox's Text property can only be set to an object of type System.String and not a null value (Nothing in VB), so the TextBox fails to bind the representative value (null/nothing) of the data source's value (DBNull) to the bound control.
The way to correct this behaviour is to ensure that the Binding class's NullValue property is explicitly set to a suitable value. In this case, a zero-length string will suffice to correct the problem.
One way to achieve this is to change the line:
Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd", True))
to:
Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd", True, DataSourceUpdateMode.OnValidation, ""))
The key here is the very last parameter, which is the NullValue, set to a zero-length string (The DataSourceUpdateMode is also explicitly specified due to the arguments of the constructor, but it's being set to it's default value anyway).
Despite all of this, it does appear to be somewhat "odd" behaviour, if not an actual bug. This is also evidenced by others who appear to be experiencing the same issue (which is still prevalent in Visual Studio 2010/.NET 4.0!). This thread on the social.msdn.microsoft.com forums contains someone experiencing the same issue with some interesting possible explanations as to why this happens, and why Microsoft designed it this way.
There is also a Microsoft Connect suggestion that was reported back in 2005 that highlights the issue. This suggestion has been "Closed as Postponed". It appears that Microsoft do not consider it a bug, as a very reasonable workaround exists (the explicit setting of the Binding's NullValue property) which, arguably, should be done anyway for readability's sake. They will apparently consider the suggestion in the future.
Going back to why this didn't exist pre-.NET 2.0 (Visual Studio 2005) seems to be due to the fact that the entire data binding mechanism was completely revamped for the release of .NET Framework 2.0. Your original solution, being a VS2003 project was using .NET Framework 1.1 which did not have as rich a data binding feature-set. Although I no longer have a copy of VS2003 to hand to test this, I'm assuming the binding mechanism in .NET 1.1 made much more use of implicit conversions between the control's value and the data source's value. This appears to be supported when you examine the Binding class from .NET 1.1, compared with .NET 2.0 (or higher). For example, there was no way to (easily) control the actual two-way binding itself (and how values are converted between the form and the data source) or the formatting of said values.
I have had this type of error before and I had to ensure that the underlying data source (in my case it was a dataset) was not set to read only and that the column allowed `null' values.
Once I had done this everything worked fine. It seemed like that the error that was being thrown in the Data Bindings was swallowed up somewhere and didn't propagate up.

Class-level Static Variable per Instance

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...