Refresh the design of a control with nested properties. VB.Net - vb.net

I was trying to make a nested property redrawing the base (a control) of his parent property.
Here is what I know:
If we use the Refresh() command supposedly it should work for what I want. Just like below.
Private Var_MyProperties_Parent As Integer
Public Property MyProperties_Parent As Integer
Get
Return Var_MyProperties_Parent
End Get
Set(value As Class_Child)
Var_MyProperties_Parent = value
Refresh()
End Set
End Property
But If I try to use it on nested properties it doesn't work, just like below.
Imports System.ComponentModel
Imports System.Globalization
Public Class Class_ParentProperty_1 : Inherits Control
Private Var_MyProperties_Parent As New Class_Child
<Browsable(True)>
<Description("Descrição não é necessária."), Category("Appearance")> ' Categoria da propriedade
<EditorBrowsable(EditorBrowsableState.Always)>
<RefreshProperties(RefreshProperties.Repaint)>
Public Property MyProperties_Parent As Class_Child
Get
Return Var_MyProperties_Parent
End Get
Set(value As Class_Child)
Var_MyProperties_Parent = value
Refresh()
End Set
End Property
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
MyBase.BackColor = MyProperties_Parent.TheMyColor
MyBase.BackgroundImage = MyProperties_Parent.SimpleImage
End Sub
End Class
<TypeConverter(GetType(Class_Child))>
Public Class Class_Child : Inherits ExpandableObjectConverter
<RefreshProperties(RefreshProperties.Repaint)>
Private Var_TheMyColor As Color = Color.Crimson
<RefreshProperties(RefreshProperties.Repaint)>
Private Var_SimpleImage As Image
<RefreshProperties(RefreshProperties.Repaint)>
Private Var_ANumber As Integer
<RefreshProperties(RefreshProperties.Repaint)>
Public Property TheMyColor As Color
Get
Return Var_TheMyColor
End Get
Set(value As Color)
Var_TheMyColor = value
End Set
End Property
<RefreshProperties(RefreshProperties.Repaint)>
Public Property SimpleImage As Image
Get
Return Var_SimpleImage
End Get
Set(value As Image)
Var_SimpleImage = value
End Set
End Property
<RefreshProperties(RefreshProperties.Repaint)>
Public Property ANumber As Integer
Get
Return Var_ANumber
End Get
Set(value As Integer)
Var_ANumber = value
End Set
End Property
Public Overrides Function ToString() As String
Return Nothing
End Function
End Class
If someone have alternatives to me or someone can explain how can I think in other way to do it or something, I would be grateful.

Related

How to hide expand button in a propertygrid in Windows Forms

I have written my on editor for a property in a propertyGrid. Everything works as expected, but for best user experience i want to hide the expand button on the propertygrid for this property. Can someone tell me how to do that?
I am using a custom typeconverter
Public Class PropertyLanguageSetupEditor
Inherits UITypeEditor
Public Overrides Function GetEditStyle(context As ITypeDescriptorContext) As UITypeEditorEditStyle
Return UITypeEditorEditStyle.Modal
End Function
Public Overrides Function EditValue(context As ITypeDescriptorContext, provider As IServiceProvider, value As Object) As Object
Try
Dim svc As IWindowsFormsEditorService = CType(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)
Dim settings As LanguageSettings = value
Dim oldSettings As LanguageSettings = CType(value, LanguageSettings).Clone
If Not svc Is Nothing And Not settings Is Nothing Then
Dim form As New PropertyLanguageSetupWindow(settings)
If svc.ShowDialog(form) = DialogResult.OK Then
value = form.Data
Else
value = oldSettings
End If
End If
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
Return MyBase.EditValue(context, provider, value)
End Function
End Class
And this is de property which uses the typeConverter
<DisplayName("Properties Translation Settings"), Editor(GetType(PropertyLanguageSetupEditor), GetType(System.Drawing.Design.UITypeEditor)), TypeConverter(GetType(BrowsableTypeConverter)),
Description("Settings for the output text"), BrowsableTypeConverter.BrowsableLabelStyleAttribute(BrowsableTypeConverter.LabelStyle.lsEllipsis),
Category("10 - DXF Export"), Browsable(True)>
Public Property TranslationSettings As LanguageSettings = New LanguageSettings
My BrowsAbleTypeConverter
Public Class BrowsableTypeConverter
Inherits ExpandableObjectConverter
Public Enum LabelStyle
lsNormal
lsTypeName
lsEllipsis
lsText
End Enum
Public Class BrowsableLabelStyleAttribute
Inherits System.Attribute
Private eLabelStyle As LabelStyle = LabelStyle.lsEllipsis
Public Sub New(ByVal LabelStyle As LabelStyle)
eLabelStyle = LabelStyle
End Sub
Public Property LabelStyle() As LabelStyle
Get
Return eLabelStyle
End Get
Set(ByVal value As LabelStyle)
eLabelStyle = value
End Set
End Property
End Class
Public Class BrowsableLabelTextAttribute
Inherits System.Attribute
Private strText As String = ""
Public Sub New(ByVal value As String)
strText = value
End Sub
Public Property Text() As String
Get
Return strText
End Get
Set(ByVal value As String)
strText = value
End Set
End Property
End Class
Public Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean
Return True
End Function
Public Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
Dim Style As BrowsableLabelStyleAttribute = context.PropertyDescriptor.Attributes(GetType(BrowsableLabelStyleAttribute))
If Not Style Is Nothing Then
Select Case Style.LabelStyle
Case LabelStyle.lsNormal
Return MyBase.ConvertTo(context, culture, value, destinationType)
Case LabelStyle.lsTypeName
Return "(" & value.GetType.Name & ")"
Case LabelStyle.lsEllipsis
Return "(...)"
Case LabelStyle.lsText
Dim text As BrowsableLabelTextAttribute = context.PropertyDescriptor.Attributes(GetType(BrowsableLabelTextAttribute))
If text IsNot Nothing Then
Return text.Text
End If
End Select
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
End Class
Your TypeConverter derives from ExpandableObjectConverter, which means subproperties will be visible because of its GetPropertiesSupported method returning true.
In your TypeConverter, you simply need to override GetPropertiesSupported and return false.

How to assign typical NumericUpDown properties to custom NumericUpDown based control?

I'm trying to make a DataGridViewColumn that inherits all of the properties of a typical NumericUpDown control. I found an answer here on StackOverflow (https://stackoverflow.com/a/55788490/692250) and a MSDN article here (https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-host-controls-in-windows-forms-datagridview-cells?view=netframeworkdesktop-4.8&redirectedfrom=MSDN#code-snippet-1).
The code from the article works well, but... I cannot assign a Maximum nor Minimum value to the control (both are stuck at the "default" Minimum of 0 and Maximum of 100).
I tried to add in code from the SO answer (by adding in a Min and Max field) but doing so locks both in to 0 and unable to change.
The question in short: how do I add the necessary properties to allow to this work.
The custom control is question:
Public Class NumericUpDownColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New NumericUpDownCell())
End Sub
Public Overrides Property CellTemplate() As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
' Ensure that the cell used for the template is a CalendarCell.
If Not (value Is Nothing) AndAlso Not value.GetType().IsAssignableFrom(GetType(NumericUpDownCell)) Then
Throw New InvalidCastException("Must be an Integer")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
Public Class NumericUpDownCell
Inherits DataGridViewTextBoxCell
Public Sub New()
' Number Format
Me.Style.Format = "0"
End Sub
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As DataGridViewCellStyle)
' Set the value of the editing control to the current cell value.
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
Dim ctl As NumericUpDownEditingControl = CType(DataGridView.EditingControl, NumericUpDownEditingControl)
ctl.Value = CType(Me.Value, Decimal)
End Sub
Public Overrides ReadOnly Property EditType() As Type
Get
' Return the type of the editing contol that CalendarCell uses.
Return GetType(NumericUpDownEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType() As Type
Get
' Return the type of the value that CalendarCell contains.
Return GetType(Decimal)
End Get
End Property
Public Overrides ReadOnly Property DefaultNewRowValue() As Object
Get
' Use the current date and time as the default value.
Return 0
End Get
End Property
End Class
Class NumericUpDownEditingControl
Inherits NumericUpDown
Implements IDataGridViewEditingControl
Private dataGridViewControl As DataGridView
Private valueIsChanged As Boolean = False
Private rowIndexNum As Integer
Public Sub New()
Me.DecimalPlaces = 0
End Sub
Public Property EditingControlFormattedValue() As Object Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Value.ToString("#")
End Get
Set(ByVal value As Object)
If TypeOf value Is Decimal Then
Me.Value = Decimal.Parse(value.ToString)
End If
End Set
End Property
Public Function GetEditingControlFormattedValue(ByVal context As DataGridViewDataErrorContexts) As Object Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.Value.ToString("#")
End Function
Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As DataGridViewCellStyle) Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
Me.Font = dataGridViewCellStyle.Font
Me.ForeColor = dataGridViewCellStyle.ForeColor
Me.BackColor = dataGridViewCellStyle.BackColor
End Sub
Public Property EditingControlRowIndex() As Integer Implements IDataGridViewEditingControl.EditingControlRowIndex
Get
Return rowIndexNum
End Get
Set(ByVal value As Integer)
rowIndexNum = value
End Set
End Property
Public Function EditingControlWantsInputKey(ByVal key As Keys, ByVal dataGridViewWantsInputKey As Boolean) As Boolean Implements IDataGridViewEditingControl.EditingControlWantsInputKey
' Let the DateTimePicker handle the keys listed.
Select Case key And Keys.KeyCode
Case Keys.Left, Keys.Up, Keys.Down, Keys.Right, Keys.Home, Keys.End, Keys.PageDown, Keys.PageUp
Return True
Case Else
Return False
End Select
End Function
Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
' No preparation needs to be done.
End Sub
Public ReadOnly Property RepositionEditingControlOnValueChange() As Boolean Implements IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property
Public Property EditingControlDataGridView() As DataGridView Implements IDataGridViewEditingControl.EditingControlDataGridView
Get
Return dataGridViewControl
End Get
Set(ByVal value As DataGridView)
dataGridViewControl = value
End Set
End Property
Public Property EditingControlValueChanged() As Boolean Implements IDataGridViewEditingControl.EditingControlValueChanged
Get
Return valueIsChanged
End Get
Set(ByVal value As Boolean)
valueIsChanged = value
End Set
End Property
Public ReadOnly Property EditingControlCursor() As Cursor Implements IDataGridViewEditingControl.EditingPanelCursor
Get
Return MyBase.Cursor
End Get
End Property
Protected Overrides Sub OnValueChanged(ByVal eventargs As EventArgs)
' Notify the DataGridView that the contents of the cell have changed.
valueIsChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnValueChanged(eventargs)
End Sub
End Class
Focusing on it a bit more, I found that I can assign values to the Maximum and Minimum fields as so:
' Set the value of the editing control to the current cell value.
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
Dim ctl As NumericUpDownEditingControl = CType(DataGridView.EditingControl, NumericUpDownEditingControl)
ctl.Value = CType(Me.Value, Decimal)
ctl.Maximum = 180
ctl.Minimum = -1
End Sub
But I cannot seem to pass to this field via the usual means of .Maximum or .Minimum on the constructor. Any tips/advice?
This is an easy fix and very easy to overlook.
In your NumericUpDownCell class you need to override the Clone method to include the new Minimum and Maximum properties, for example:
First, add the new properties the NumericUpDownCell class and then override the Clone function
Public Class NumericUpDownCell
Inherits DataGridViewTextBoxCell
...
Public Property Minimum() As Integer
Public Property Maximum() As Integer
...
Public Overrides Function Clone() As Object
Dim retVal As NumericUpDownCell = CType(MyBase.Clone, NumericUpDownCell)
retVal.Minimum = Me.Minimum
retVal.Maximum = Me.Maximum
Return retVal
End Function
End Class
Second, inside the NumericUpDownCell classes InitializeEditingControl method, add the two lines:
ctl.Minimum = Me.Minimum
ctl.Maximum = Me.Maximum
When you setup the new column, get the CellTemplate to set the new properties, as per:
Dim upDownColumn As New NumericUpDownColumn
Dim cellTemplate As NumericUpDownCell = CType(upDownColumn .CellTemplate, NumericUpDownCell)
cellTemplate.Minimum = 10
cellTemplate.Maximum = 15
Or, following you preference to setup via the constructor, add a new constructor to the NumericUpdDownColumn class as per
Public Sub New(minValue As Integer, maxValue As Integer)
MyBase.New(New NumericUpDownCell())
Dim template As NumericUpDownCell = CType(CellTemplate, NumericUpDownCell)
template.Minimum = minValue
template.Maximum = maxValue
End Sub
and then use it like:
Dim upDownColumn As New NumericUpDownColumn(100, 150)
Dim cellTemplate As NumericUpDownCell = CType(upDownColumn.CellTemplate, NumericUpDownCell)
DataGridView1.Columns.Add(upDownColumn)

Getting a property from the instantiator class

Not an experienced programmer, so probably not a hard question.
Developing a small application in VB.net in WPF.
I made 3 classes, EngineeringObject<==Inherits==PartOfInstallation<==Inherits==SensorActor
In the class SensorActor I'm trying to get a property of PartOfInstallation with the function MyBase.Name. But this goes directly to EngineeringObject. How do I solve this?
Public Class EngineeringObject
''Private declarations, alleen objecten die erven kunnen hieraan, of dmv van getters en setters
'Name of part
Private sName As String = "Naam"
'81346 Id's
Private sSystemId As String = "Functie" 'VentilationSystem, Pumpsystem
Private sLocationId As String = "Locatie" 'Room 0.0
Private sObjectId As String = "Object" 'Fan, Pump
'General
Private sPartNumber As String
Private sLinkToDatasheet As String
'Property's
Public Property Name() As String
Get
Return sName
End Get
Set(ByVal value As String)
sName = value
End Set
End Property
Public Property SystemId() As String
Get
Return sSystemId
End Get
Set(ByVal value As String)
sSystemId = value
End Set
End Property
Public Property PartNumber() As String
Get
Return sPartNumber
End Get
Set(ByVal value As String)
sPartNumber = value
End Set
End Property
Public Property LinkToDatasheet() As String
Get
Return sLinkToDatasheet
End Get
Set(ByVal value As String)
sLinkToDatasheet = value
End Set
End Property
Public Sub New()
End Sub
End Class
Public Class PartOfInstallation
Inherits EngineeringObject
'src: https://stackoverflow.com/questions/21308881/parent-creating-child-object
'src: https://stackoverflow.com/questions/16244548/how-to-create-a-list-of-parent-objects-where-each-parent-can-have-a-list-of-chil
Private lSensorActor As New List(Of SensorActor)
Public Function GetSensorActor()
Return Me.lSensorActor
End Function
Public Sub CreateSensorActor()
lSensorActor.Add(New SensorActor)
End Sub
End Class
Public Class SensorActor
Inherits PartOfInstallation
Dim sMyPartOfInstallation As String
Public Property MyPartOfInstallation As String
Get
Return sMyPartOfInstallation
End Get
Set(value As String)
sMyPartOfInstallation = MyBase.Name
End Set
End Property
End Class
If I understand it correctly, based on your comments, you want every SensorActor instantiated within a PartOfInstallation instance to get the same name as that instance.
If so, then just add a second constructor to your SensorActor class allowing you to pass a name for it as well:
Public Class SensorActor
Inherits PartOfInstallation
...your code...
Public Sub New() 'Empty constructor, for if/when you don't want to set the name immediately.
End Sub
Public Sub New(ByVal Name As String)
Me.Name = Name
End Sub
End Class
Now in your PartOfInstallation class you can do:
Public Sub CreateSensorActor()
lSensorActor.Add(New SensorActor(Me.Name)) 'Here, "Me" refers to the current PartOfInstallation instance.
End Sub
Alternatively you can make the SensorActor constructor take a PartOfInstallation instance instead, allowing you to copy any properties you like:
Public Class SensorActor
Inherits PartOfInstallation
...your code...
Public Sub New()
End Sub
Public Sub New(ByVal BasedOnPOI As PartOfInstallation)
Me.Name = BasedOnPOI.Name
End Sub
End Class
Thus making the code in the PartOfInstallation class:
Public Sub CreateSensorActor()
lSensorActor.Add(New SensorActor(Me))
End Sub
Read more about constructors: Object Lifetime: How Objects Are Created and Destroyed (Visual Basic) | Microsoft Docs
The result below, if there's room for improvement... always welcome.
SensorActor
Public Class SensorActor
Inherits PartOfInstallation
Dim sTemp As String
Public Overloads Property SystemId() As String
Get
Return Me.sSystemId
End Get
Set(ByVal value As String)
Me.sSystemId = sTemp + "." + value
End Set
End Property
Public Sub New(ByVal BasedOnPOI As PartOfInstallation)
sTemp = BasedOnPOI.SystemId
End Sub
End Class
PartOfInstallation
Public Class PartOfInstallation
Inherits EngineeringObject
'src: https://stackoverflow.com/questions/21308881/parent-creating-child-object
'src: https://stackoverflow.com/questions/16244548/how-to-create-a-list-of-parent-objects-where-each-parent-can-have-a-list-of-chil
Private lSensorActor As New List(Of SensorActor)
Public Function GetSensorActor()
Return Me.lSensorActor
End Function
Public Sub CreateSensorActor()
lSensorActor.Add(New SensorActor(Me))
End Sub
End Class
EngineeringObject
Public Class EngineeringObject
''Private declarations, alleen objecten die erven kunnen hieraan, of dmv van getters en setters
'Name of part
Private sName As String = "Naam"
'81346 Id's
Friend sSystemId As String = "Functie" 'VentilationSystem, Pumpsystem
Private sLocationId As String = "Locatie" 'Room 0.0
Private sObjectId As String = "Object" 'Fan, Pump
'General
Private sPartNumber As String
Private sLinkToDatasheet As String
'Property's
Public Property Name() As String
Get
Return sName
End Get
Set(ByVal value As String)
sName = value
End Set
End Property
Public Property SystemId() As String
Get
Return sSystemId
End Get
Set(ByVal value As String)
sSystemId = "=" + value
End Set
End Property
Public Property PartNumber() As String
Get
Return sPartNumber
End Get
Set(ByVal value As String)
sPartNumber = value
End Set
End Property
Public Property LinkToDatasheet() As String
Get
Return sLinkToDatasheet
End Get
Set(ByVal value As String)
sLinkToDatasheet = value
End Set
End Property
Public Sub New()
End Sub
End Class

VB.NET Databound Label not updating

I am having issues with a label with a databound text value updating. I have a Class that calculates the best throw of an athlete and this is bound to a label in my form. The class is as follows
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Public Class Competition
Public Sub New()
Competitors = New List(Of Competitor)()
End Sub
Public Property Competitors() As List(Of Competitor)
Get
Return m_Competitors
End Get
Set(value As List(Of Competitor))
m_Competitors = value
End Set
End Property
Private m_Competitors As List(Of Competitor)
Public ReadOnly Property CurrentPlacings() As List(Of Competitor)
Get
Return Competitors.OrderByDescending(Function(c) c.BestThrow).ToList()
End Get
End Property
End Class
Public Class Competitor
Implements System.ComponentModel.INotifyPropertyChanged
Public Event PropertyChanged(sender As Object,
e As System.ComponentModel.PropertyChangedEventArgs) _
Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Public Sub New()
Throws = New List(Of [Throw])()
End Sub
Public Property FirstName() As String
Get
Return m_FirstName
End Get
Set(value As String)
m_FirstName = value
End Set
End Property
Private m_FirstName As String
Public Property LastName() As String
Get
Return m_LastName
End Get
Set(value As String)
m_LastName = value
End Set
End Property
Private m_LastName As String
Public Property compNumber() As String
Get
Return m_compNumb
End Get
Set(value As String)
m_compNumb = value
End Set
End Property
Private m_compNumb As String
Public Property club() As String
Get
Return m_club
End Get
Set(value As String)
m_club = value
End Set
End Property
Private m_club As String
Public Property Throws() As List(Of [Throw])
Get
Return m_Throws
End Get
Set(value As List(Of [Throw]))
m_Throws = value
End Set
End Property
Private m_Throws As List(Of [Throw])
Public ReadOnly Property BestThrow() As Object
Get
Dim bt = Throws.Where(Function(t) t.Status = ThrowStatus.Valid).OrderByDescending(Function(t) t.Distance).First()
If (IsNothing(bt.Distance)) Then
bt.Distance = "0"
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("BestThrow"))
Return bt
End Get
End Property
Public ReadOnly Property getLabel
Get
Return compNumber & " " & LastName & ", " & FirstName & vbCrLf & club
End Get
End Property
End Class
Public Enum ThrowStatus
Valid
Pass
Foul
End Enum
Public Class [Throw]
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Property Status() As ThrowStatus
Get
Return m_Status
End Get
Set(value As ThrowStatus)
m_Status = value
End Set
End Property
Private m_Status As ThrowStatus
Public Property Distance() As String
Get
If Status = ThrowStatus.Valid Then
If (m_Distance > 0) Then
Return m_Distance
Else
Return Nothing
End If
ElseIf Status = ThrowStatus.Pass Then
Return "PASS"
ElseIf Status = ThrowStatus.Foul Then
Return "FOUL"
Else
Return Nothing
End If
End Get
Set(value As String)
If (value > 0) Then
If (IsNumeric(value)) Then
m_Distance = value
Status = ThrowStatus.Valid
ElseIf (value = "foul") Then
Status = ThrowStatus.Foul
ElseIf (value = "pass") Then
Status = ThrowStatus.Pass
Else
Status = ThrowStatus.Valid
m_Distance = Nothing
End If
Else
m_Distance = Nothing
Status = ThrowStatus.Valid
End If
OnPropertyChanged("Distance")
End Set
End Property
Protected Sub OnPropertyChanged(ByVal name As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
End Sub
Private m_Distance As Decimal
Public Property attempt() As Integer
Get
Return m_attempt
End Get
Set(value As Integer)
m_attempt = value
End Set
End Property
Private m_attempt As Integer
End Class
The line that databinds for the Label is as follows:
best.DataBindings.Add(New Binding("text", athlete.BestThrow, "distance", False, DataSourceUpdateMode.OnPropertyChanged))
I can tell that the Property BestThrow is defintely being updated using Watch however for some reason the label seems to only reflect Throw(0).Distance and not BestThrow.Distance
I can change Throw(0) and the label will change, if I add a bigger number to any of the other 5 attempts and Watch the value I can see that the BestThrow is being updated.
Thanks in advance for your assistance.
Mark
I think you have a wrong prespective, property BestThrow is never updated because it has no setter. When you check BestThrow value using watch, it 'recalculated' because you request the value. What you need is to find a way to raise Property Changed event for BestThrow whenever item added or removed from Throws because BestThrow value depends on Throws. After event raised, UI will call BestThrow's getter again looking for updated value.
'You need to execute this code to notify UI that `BestThrow` value has changed
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("BestThrow"))
Raisng the event can be done manually after code for adding/removing item to/from Throws property, or you can make Throws an ObservableCollection of Throw then listen to Collection Changed event. Then in the event handler you can raise BestThrow property changed event.

how to loop inside every tables/columns in a dbml file to create new partial class with more information about every columns

I have a class that add extra information about a column for linq2sql (see code below)
right now, I have to explicitly tell what column I want that info on, how would you put that code with a loop on every column in every table from a dbml file?
I was doing my test on a very very small DB, now I have to implement it on a much more bigger database and I really don't want to do it manually for every tables/columns
it will take hours.
how it's being used:
Partial Class Contact ''contact is a table inside a dbml file.
Private _ContactIDColumn As ExtraColumnInfo
Private _ContactNameColumn As ExtraColumnInfo
Private _ContactEmailColumn As ExtraColumnInfo
Private _ContactTypeIDColumn As ExtraColumnInfo
Private Sub OnCreated()
initColumnInfo()
End Sub
Private Sub initColumnInfo()
Dim prop As PropertyInfo
prop = Me.GetType.GetProperty("ContactID")
_ContactIDColumn = New ExtraColumnInfo(DirectCast(prop.GetCustomAttributes(GetType(ColumnAttribute), False)(0), ColumnAttribute))
prop = Me.GetType.GetProperty("ContactName")
_ContactNameColumn = New ExtraColumnInfo(DirectCast(prop.GetCustomAttributes(GetType(ColumnAttribute), False)(0), ColumnAttribute))
prop = Me.GetType.GetProperty("ContactEmail")
_ContactEmailColumn = New ExtraColumnInfo(DirectCast(prop.GetCustomAttributes(GetType(ColumnAttribute), False)(0), ColumnAttribute))
prop = Me.GetType.GetProperty("ContactTypeID")
_ContactTypeIDColumn = New ExtraColumnInfo(DirectCast(prop.GetCustomAttributes(GetType(ColumnAttribute), False)(0), ColumnAttribute))
prop = Nothing
End Sub
Public ReadOnly Property ContactIDColumn() As ExtraColumnInfo
Get
Return _ContactIDColumn
End Get
End Property
Public ReadOnly Property ContactNameColumn() As ExtraColumnInfo
Get
Return _ContactNameColumn
End Get
End Property
Public ReadOnly Property ContactEmailColumn() As ExtraColumnInfo
Get
Return _ContactEmailColumn
End Get
End Property
Public ReadOnly Property ContactTypeIDColumn() As ExtraColumnInfo
Get
Return _ContactTypeIDColumn
End Get
End Property
End Class
what is ExtraColumnInfo:
Public Class ExtraColumnInfo
Private _column As ColumnAttribute
Private _MaxLength As Nullable(Of Integer)
Private _Precision As Nullable(Of Integer)
Private _Scale As Nullable(Of Integer)
Private _IsIdentity As Boolean
Private _IsUniqueIdentifier As Boolean
Sub New(ByVal column As ColumnAttribute)
Dim match As Match
_column = column
Match = Regex.Match(DBType, "^.*\((\d+)\).*$", RegexOptions.Compiled Or RegexOptions.IgnoreCase)
_MaxLength = If(match.Success, Convert.ToInt32(match.Groups(1).Value), Nothing)
match = Regex.Match(DBType, "^.*\((\d+),(\d+)\).*$", RegexOptions.Compiled Or RegexOptions.IgnoreCase)
_Precision = If(Match.Success, Convert.ToInt32(Match.Groups(1).Value), Nothing)
match = Regex.Match(DBType, "^.*\((\d+),(\d+)\).*$", RegexOptions.Compiled Or RegexOptions.IgnoreCase)
_Scale = If(match.Success, Convert.ToInt32(match.Groups(2).Value), Nothing)
match = Regex.Match(DBType, "^.*\bIDENTITY\b.*$", RegexOptions.Compiled Or RegexOptions.IgnoreCase)
_IsIdentity = match.Success
match = Regex.Match(DBType, "^.*\bUniqueIdentifier\b.*$", RegexOptions.Compiled Or RegexOptions.IgnoreCase)
_IsUniqueIdentifier = match.Success
End Sub
'others available information
'AutoSync
'Expression
'IsVersion
'Name
'Storage
'TypeId
'UpdateCheck
'maybe more
Public ReadOnly Property CanBeNull() As Boolean
Get
Return _column.CanBeNull
End Get
End Property
Public ReadOnly Property IsDbGenerated() As Boolean
Get
Return _column.IsDbGenerated
End Get
End Property
Public ReadOnly Property IsPrimaryKey() As Boolean
Get
Return _column.IsPrimaryKey
End Get
End Property
Public ReadOnly Property DBType() As String
Get
Return _column.DbType
End Get
End Property
Public ReadOnly Property MaxLength() As System.Nullable(Of Integer)
Get
Return _MaxLength
End Get
End Property
Public ReadOnly Property Precision() As System.Nullable(Of Integer)
Get
Return _Precision
End Get
End Property
Public ReadOnly Property Scale() As System.Nullable(Of Integer)
Get
Return _Scale
End Get
End Property
Public ReadOnly Property IsIdentity() As Boolean
Get
Return _IsIdentity
End Get
End Property
Public ReadOnly Property IsUniqueIdentifier() As Boolean
Get
Return _IsUniqueIdentifier
End Get
End Property
End Class
The only thing that comes to mind, and it's a far from optimal solution, would be to include this functionality into a base class and declare partials for all of the generated classes so that they inherit from your base class.
I'm sure there are also other ways to do this, but none that I know of that are native to the designer.
I took the T4 template and modified it a little to automatically put inside the generated class the column information,
in the import I added
Imports System.Reflection
Imports System.Text.RegularExpressions
at line 228, added these line:
<# foreach(Column column in class1.Columns) {#>
Private _<#=column.Member#>Column As ExtraColumnInfo
Public ReadOnly Property <#=column.Member#>Column() As ExtraColumnInfo
Get
Return _<#=column.Member#>Column
End Get
End Property
<# }#>
at line 298 I added
Dim prop As PropertyInfo
<# foreach(Column column in class1.Columns) {#>
prop = Me.GetType.GetProperty("<#=column.Member#>")
_<#=column.Member#>Column = New ExtraColumnInfo(DirectCast(prop.GetCustomAttributes(GetType(ColumnAttribute), False)(0), ColumnAttribute))
<# }#>
at the end of the file, I added my own class