I have a LINQ to SQL generated class with a readonly property:
<Column(Name:="totalLogins", Storage:="_TotalLogins", DbType:="Int", UpdateCheck:=UpdateCheck.Never)> _
Public ReadOnly Property TotalLogins() As System.Nullable(Of Integer)
Get
Return Me._TotalLogins
End Get
End Property
This prevents it from being changed externally, but I would like to update the property from within my class like below:
Partial Public Class User
...
Public Shared Sub Login(Username, Password)
ValidateCredentials(UserName, Password)
Dim dc As New MyDataContext()
Dim user As User = (from u in dc.Users select u where u.UserName = Username)).FirstOrDefault()
user._TotalLogins += 1
dc.SubmitChanges()
End Sub
...
End Class
But the call to user._TotalLogins += 1 is not being written to the database? Any thoughts on how to get LINQ to see my changes?
Set the existing TotalLogins property as either private or protected and remove the readonly attribute. You may also want to rename it e.g. InternalTotalLogins.
Then create a new property by hand in the partial class that exposes it publically as a read-only property:
Public ReadOnly Property TotalLogins() As System.Nullable(Of Integer)
Get
Return Me.InternalTotalLogins
End Get
End Property
Make a second property that is protected or internal(?)
<Column(Name:="totalLogins", Storage:="_TotalLogins", DbType:="Int", UpdateCheck:=UpdateCheck.Never)> _
protected Property TotalLogins2() As System.Nullable(Of Integer)
Get
Return Me._TotalLogins
End Get
Set(byval value as System.Nullable(Of Integer))
Return Me._TotalLogins
End Get
End Property
and then update that . I think it won't save readonly properties by default. And why should it anyway. I now it's a hack but hey that's life.
Before you change the field call SendPropertyChanging() and then after call SendPropertyChanged("").
This will make the Table entity tracking know something changed.
Related
I have a user control with a property "Rules" that is a generic list.
Every "rule" is associated to a combobox control and i have to create a property to host data for the combobox. I used another generic list to accomplish this.
In design works well, i can add items normally in property grid, but when i run the program the values are not maintained.
Rules property:
Private _regras As New List(Of ParametrosColunasGrid)
<Category("Ecletica")> _
<Browsable(True)> _
<System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Content)>
Public Property Regras() As List(Of ParametrosColunasGrid)
Get
Return _regras
End Get
Set(value As List(Of ParametrosColunasGrid))
_regras = value
End Set
End Property
Public Class ParametrosColunasGrid
'...
Private _itens_Combo As New List(Of ItemComboBox)
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public Property ItensCombo As List(Of ItemComboBox)
Get
Return _itens_Combo
End Get
Set(value As List(Of ItemComboBox))
_itens_Combo = value
End Set
End Property
'...
End Class
ItemComboBox Class:
<Serializable()>
Public Class ItemComboBox
Public Property Value As String
Public Property Key As String
Public Overrides Function ToString() As String
Return _Value
End Function
End Class
.NET Gurus,
I have picked up another developers work and I have created a Class Level Public Property boolean isNewValue
However, I cannot access this Property from the "Shared" Subs or Functions that are Public or <WebMethods> that are Public Shared Functions.
I do not understand why, could someone explain?
' Public Property scoped as Public in the Public Class Class_Name
Public Property isNewValueCode As Boolean
Get
Return _isNewValueCode
End Get
Set(ByVal value As Boolean)
_isNeValuewSrvCode = value
End Set
End Property
Later on in the code I have:
Shared Function GetDataItem(ByRef db As myEntities) As CodeDataItem
THIS IS WHERE I NEED TO BE ADD AN IF
If isNewValueCode Then 'Cannot see the isNewValueCode
Dim data As New CodeDataItem
Dim code = db.tbl_services.FirstOrDefault(Function(x) x.id = TargetID)
If (Not code Is Nothing) Then
data = New CodeDataItem(code)
End If
Else
'New code going against different db.tables in Entity Context
End If
Return data
End Function
enter code here
You can not access non shared class members from shared functions without an instance of that class. So to be able to access isNewValueCode you need an instance of what ever class the property belongs to.
Depending on you requirements you could possibly change the property to be shared also, but than it would no longer be a member of any instance of that class.
I imagine you have something simular to this:
Private _isNewValueCode As Boolean
Private _isNeValuewSrvCode As Boolean
Public Property isNewValueCode As Boolean
Get
Return _isNewValueCode
End Get
Set(ByVal value As Boolean)
_isNeValuewSrvCode = value
End Set
End Property
You have a couple of options here, you can make isNewValue and it's private constructors shared like so:
Private Shared _isNewValueCode As Boolean
Private Shared _isNeValuewSrvCode As Boolean
Public Shared Property isNewValueCode As Boolean
Get
Return _isNewValueCode
End Get
Set(ByVal value As Boolean)
_isNeValuewSrvCode = value
End Set
End Property
Or Assuming isNeValuewSrvCode is a copy paste error and you really wanted to assign it back to the same variable, you could simply do this:
Public Shared Property isNewValueCode As Boolean
Take a look at the MSDN Description of shared properties for more info on what exactly the shared keyword does.
Having a bit of a brain fart, right before bed. But i have the need to remap a ReadOnly Property from one name to a specified name i want.
I figured i could do
Public Readonly Property DocName as String
Get
Return Mybase.Name
End Get
End Property
And yes i am trying to remap the Name Property for an XMLDocument object. Just want to make sure that as long as i declare this property and then type:
Public Overrides ReadOnly Property Name As String
Get
Return SomeValue
End Get
End Property
I will be good togo? I know i will get the method has multiple definitions with identical signatures message, which brings me to my 2nd Question:
How do i prevent the Multiple Signatures error message from popping up with this type of declaration?
Unless i am missing some declaration attribute for this type of override.
You can use Shadows to accomplish this:
Public Class A
Public ReadOnly Property Name As String
Get
Return "Name"
End Get
End Property
End Class
Public Class B
Inherits A
Public ReadOnly Property DocName As String
Get
Return MyBase.Name
End Get
End Property
Public Shadows ReadOnly Property Name As String
Get
Return "SomeValue"
End Get
End Property
End Class
I am trying to implement a way of persisting a collection in a custom settings class. I have successfully created the settings class (inheriting ApplicationSettingsBase) and can save properties using the built-in editors on a PropertyGrid, but my custom implementation of a property grid for collections doesn't persist any of the values I add. Here's my code:
Imports System.Configuration
Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.ComponentModel.Design
Public Class CustomSettings
Inherits ApplicationSettingsBase
<UserScopedSetting()> _
<DefaultSettingValue("White")> _
Public Property BackgroundColor() As Color
Get
BackgroundColor = Me("BackgroundColor")
End Get
Set(ByVal value As Color)
Me("BackgroundColor") = value
End Set
End Property
<UserScopedSetting()> _
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
<Editor(GetType(CustomStringCollectionEditor), GetType(UITypeEditor))> _
Public Property EmailAddresses() As Collection
Get
EmailAddresses = Me("EmailAddresses")
End Get
Set(ByVal value As Collection)
Me("EmailAddresses") = value
End Set
End Property
End Class
Public Class CustomStringCollectionEditor
Inherits CollectionEditor
Public Sub New()
MyBase.New(GetType(Collection))
End Sub
Protected Overrides Function CreateInstance(ByVal itemType As System.Type) As Object
Return String.Empty
End Function
Protected Overrides Function CreateCollectionItemType() As System.Type
Return GetType(String)
End Function
End Class
I set a breakpoint on the Set methods for both the BackgroundColor property and the EmailAddresses property. The BackgroundColor property works as it should - it breaks on the Set statement and stores the property correctly. But when I close the custom CollectionEditor dialog, the EmailAddresses "Set" method is never called. How can I get my custom editor to actually save the property once it's done being edited?
I think I fixed it (with help from this question). I added an override to the EditValue function in my custom editor. Here is the code:
Public Overrides Function EditValue(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal provider As System.IServiceProvider, ByVal value As Object) As Object
Dim result As Object = MyBase.EditValue(context, provider, value)
DirectCast(context.Instance, CustomSettings).EmailAddresses = DirectCast(result, List(Of String))
Return result
End Function
I also moved from a collection to a list - I read somewhere that was a safer way to go. I also added a constructor to my CustomSettings class that set the EmailAddresses property to a new List(Of String) if it was unset to begin with. I found that the first time it ran, I could edit the list and add items, but they wouldn't be persisted:
Public Sub New()
If Me("EmailAddresses") Is Nothing Then
Me("EmailAddresses") = New List(Of String)
End If
End Sub
And now it's all working like it should. But if this isn't the best way or there's an easier way to do it, please chime in.
I've created a custom user control that has several properties. One specifies which database I want the control to access. I want to be able to present the user of the control a drop down from which he can select which database the control will interact with.
How do I get the dropdown to work? I can get default values, but have yet to figure out how to get the selectable list.
Any help is apprectiated.
Thanks.
Marshall
You just need to attach your own TypeConverter to your property. You will override the GetStandardValuesSupported and GetStandardValues methods (maybe GetStandardValuesExclusive too) to return the list of databases you want to show.
If you are new to the PropertyGrid and the TypeConverter, here is a document.
It turns out to be simpler than I thought.
I had an enumeration set up for the property, but was having trouble using it for the property type. Said it was unaccessable outside of the class.
Then I had a 'duh' moment and changed the enumeration from Friend to Public, and then I was able to use the enumeration as the property type. As a result the values from the enumeration are listed in a dropdown when I look at the values for that property of the controls.
Thanks to all that answered.
Marshall
I'm a little confused about your problem.
If your user control contains a DropDownList control, just inititalize somewhere in the user control.
The easiest way is in the Codebehind for the usercontrol, just do DropDownList.Items.Add() or whatever the syntax is for adding an item.
Here is the template I use to create a custom datasource for my comboboxes:
Private Class Listing
Private _List As New ArrayList
Public Sub Add(ByVal ItemNumber As Integer, ByVal ItemName As String)
_List.Add(New dataItem(ItemNumber, ItemName))
End Sub
Public ReadOnly Property List() As ArrayList
Get
Return _List
End Get
End Property
End Class
Private Class dataItem
Private _ItemNumber As Integer
Private _ItemName As String
Public Sub New(ByVal intItemNumber As Integer, ByVal strItemName As String)
Me._ItemNumber = intItemNumber
Me._ItemName = strItemName
End Sub
Public ReadOnly Property ItemName() As String
Get
Return _ItemName
End Get
End Property
Public ReadOnly Property ItemNumber() As Integer
Get
Return _ItemNumber
End Get
End Property
Public ReadOnly Property DisplayValue() As String
Get
Return CStr(Me._ItemNumber).Trim & " - " & _ItemName.Trim
End Get
End Property
Public Overrides Function ToString() As String
Return CStr(Me._ItemNumber).Trim & " - " & _ItemName.Trim
End Function
End Class
And this is how I load it:
ListBindSource = New Listing
Me.BindingSource.MoveFirst()
For Each Row As DataRowView In Me.BindingSource.List
Dim strName As String = String.Empty
Dim intPos As Integer = Me.BindingSource.Find("Number", Row("Number"))
If intPos > -1 Then
Me.BindingSource.Position = intPos
strName = Me.BindingSource.Current("Name")
End If
ListBindSource.Add(Row("Number"), strName)
Next
cboNumber.DataSource = ListBindSource.POList
cboNumber.DisplayMember = "DisplayValue"
cboNumber.ValueMember = "Number"
AddHandler cboNumber.SelectedIndexChanged, AddressOf _
cboNumber_SelectedIndexChanged
Hope this helps. One thing to keep in mind is that if cboNumber has a handler already assigned to the SelectedIndexchanged event, you will encounter problems. So don't create a default event.