Wpf AttachedBehavior losing base textbox functionalty when using it - wpf

I have a attached behavior issue. When I attach the behavior to my textbox I lose all my base functionality like the Max length? Here is how I am attaching it in my xaml. When I take off the attached behavior the max length work when I put it back on it doesnt work? Any help would be greatly appreciated!
This is the class I am using
Imports System.Windows
Imports System.Windows.Controls
Imports System.Globalization
Namespace AttachedBehaviours
Public Class TextBoxMaskBehavior
Inherits DependencyObject
Region "MinimumValue Property"
Public Shared Function GetMinimumValue(ByVal obj As DependencyObject) As Double
Return CDbl(obj.GetValue(MinimumValueProperty))
End Function
Public Shared Sub SetMinimumValue(ByVal obj As DependencyObject, ByVal value As Double)
obj.SetValue(MinimumValueProperty, value)
End Sub
Public Shared ReadOnly MinimumValueProperty As DependencyProperty = DependencyProperty.RegisterAttached("MinimumValue", GetType(Double), GetType(TextBoxMaskBehavior), New FrameworkPropertyMetadata(Double.NaN, AddressOf MinimumValueChangedCallback))
Private Shared Sub MinimumValueChangedCallback(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
Dim _this As TextBox = TryCast(d, TextBox)
ValidateTextBox(_this)
End Sub
End Region
Region "MaximumValue Property"
Public Shared Function GetMaximumValue(ByVal obj As DependencyObject) As Double
Return CDbl(obj.GetValue(MaximumValueProperty))
End Function
Public Shared Sub SetMaximumValue(ByVal obj As DependencyObject, ByVal value As Double)
obj.SetValue(MaximumValueProperty, value)
End Sub
Public Shared ReadOnly MaximumValueProperty As DependencyProperty = DependencyProperty.RegisterAttached("MaximumValue", GetType(Double), GetType(TextBoxMaskBehavior), New FrameworkPropertyMetadata(Double.NaN, AddressOf MaximumValueChangedCallback))
Private Shared Sub MaximumValueChangedCallback(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
Dim _this As TextBox = TryCast(d, TextBox)
ValidateTextBox(_this)
End Sub
End Region
Region "Mask Property"
Public Shared Function GetMask(ByVal obj As DependencyObject) As MaskType
Return CType(obj.GetValue(MaskProperty), MaskType)
End Function
Public Shared Sub SetMask(ByVal obj As DependencyObject, ByVal value As MaskType)
obj.SetValue(MaskProperty, value)
End Sub
Public Shared ReadOnly MaskProperty As DependencyProperty = DependencyProperty.RegisterAttached("Mask", GetType(MaskType), GetType(TextBoxMaskBehavior), New FrameworkPropertyMetadata(AddressOf MaskChangedCallback))
Private Shared Sub MaskChangedCallback(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
If TypeOf e.OldValue Is TextBox Then
RemoveHandler TryCast(e.OldValue, TextBox).PreviewTextInput, AddressOf TextBox_PreviewTextInput
DataObject.RemovePastingHandler(TryCast(e.OldValue, TextBox), DirectCast(AddressOf TextBoxPastingEventHandler, DataObjectPastingEventHandler))
End If
Dim _this As TextBox = TryCast(d, TextBox)
If _this Is Nothing Then
Return
End If
If CType(e.NewValue, MaskType) <> MaskType.Any Then
AddHandler _this.PreviewTextInput, AddressOf TextBox_PreviewTextInput
DataObject.AddPastingHandler(_this, DirectCast(AddressOf TextBoxPastingEventHandler, DataObjectPastingEventHandler))
End If
ValidateTextBox(_this)
End Sub
End Region
Region "Private Static Methods"
Private Shared Sub ValidateTextBox(ByVal _this As TextBox)
If GetMask(_this) <> MaskType.Any Then
_this.Text = ValidateValue(GetMask(_this), _this.Text, GetMinimumValue(_this), GetMaximumValue(_this))
End If
End Sub
Private Shared Sub TextBoxPastingEventHandler(ByVal sender As Object, ByVal e As DataObjectPastingEventArgs)
Dim _this As TextBox = TryCast(sender, TextBox)
Dim clipboard As String = TryCast(e.DataObject.GetData(GetType(String)), String)
clipboard = ValidateValue(GetMask(_this), clipboard, GetMinimumValue(_this), GetMaximumValue(_this))
If Not String.IsNullOrEmpty(clipboard) Then
_this.Text = clipboard
End If
e.CancelCommand()
e.Handled = True
End Sub
Private Shared Sub TextBox_PreviewTextInput(ByVal sender As Object, ByVal e As System.Windows.Input.TextCompositionEventArgs)
Dim _this As TextBox = TryCast(sender, TextBox)
Dim isValid As Boolean = IsSymbolValid(GetMask(_this), e.Text)
e.Handled = Not isValid
If isValid Then
Dim caret As Integer = _this.CaretIndex
Dim text As String = _this.Text
Dim textInserted As Boolean = False
Dim selectionLength As Integer = 0
If _this.SelectionLength > 0 Then
text = text.Substring(0, _this.SelectionStart) & text.Substring(_this.SelectionStart + _this.SelectionLength)
caret = _this.SelectionStart
End If
If e.Text = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator Then
While True
Dim ind As Integer = text.IndexOf(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
If ind = -1 Then
Exit While
End If
text = text.Substring(0, ind) & text.Substring(ind + 1)
If caret > ind Then
caret -= 1
End If
End While
If caret = 0 Then
text = "0" & text
caret += 1
Else
If caret = 1 AndAlso String.Empty & text(0) = NumberFormatInfo.CurrentInfo.NegativeSign Then
text = NumberFormatInfo.CurrentInfo.NegativeSign & "0" & text.Substring(1)
caret += 1
End If
End If
If caret = text.Length Then
selectionLength = 1
textInserted = True
text = text & NumberFormatInfo.CurrentInfo.NumberDecimalSeparator & "0"
caret += 1
End If
ElseIf e.Text = NumberFormatInfo.CurrentInfo.NegativeSign Then
textInserted = True
If _this.Text.Contains(NumberFormatInfo.CurrentInfo.NegativeSign) Then
text = text.Replace(NumberFormatInfo.CurrentInfo.NegativeSign, String.Empty)
If caret <> 0 Then
caret -= 1
End If
Else
text = NumberFormatInfo.CurrentInfo.NegativeSign + _this.Text
caret += 1
End If
End If
If Not textInserted Then
text = text.Substring(0, caret) & Convert.ToString(e.Text) & (If((caret < _this.Text.Length), text.Substring(caret), String.Empty))
caret += 1
End If
Try
Dim val As Double = Convert.ToDouble(text)
Dim newVal As Double = ValidateLimits(GetMinimumValue(_this), GetMaximumValue(_this), val)
If val <> newVal Then
text = newVal.ToString()
ElseIf val = 0 Then
If Not text.Contains(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator) Then
text = "0"
End If
End If
Catch
text = "0"
End Try
While text.Length > 1 AndAlso text(0) = "0"c AndAlso String.Empty & text(1) <> NumberFormatInfo.CurrentInfo.NumberDecimalSeparator
text = text.Substring(1)
If caret > 0 Then
caret -= 1
End If
End While
While text.Length > 2 AndAlso String.Empty & text(0) = NumberFormatInfo.CurrentInfo.NegativeSign AndAlso text(1) = "0"c AndAlso String.Empty & text(2) <> NumberFormatInfo.CurrentInfo.NumberDecimalSeparator
text = NumberFormatInfo.CurrentInfo.NegativeSign & text.Substring(2)
If caret > 1 Then
caret -= 1
End If
End While
If caret > text.Length Then
caret = text.Length
End If
_this.Text = text
_this.CaretIndex = caret
_this.SelectionStart = caret
_this.SelectionLength = selectionLength
e.Handled = True
End If
End Sub
Private Shared Function ValidateValue(ByVal mask As MaskType, ByVal value As String, ByVal min As Double, ByVal max As Double) As String
If String.IsNullOrEmpty(value) Then
Return String.Empty
End If
value = value.Trim()
Select Case mask
Case MaskType.[Integer]
Try
Convert.ToInt64(value)
Return value
Catch
End Try
Return String.Empty
Case MaskType.[Decimal]
Try
Convert.ToDouble(value)
Return value
Catch
End Try
Return String.Empty
End Select
Return value
End Function
Private Shared Function ValidateLimits(ByVal min As Double, ByVal max As Double, ByVal value As Double) As Double
If Not min.Equals(Double.NaN) Then
If value < min Then
Return min
End If
End If
If Not max.Equals(Double.NaN) Then
If value > max Then
Return max
End If
End If
Return value
End Function
Private Shared Function IsSymbolValid(ByVal mask As MaskType, ByVal str As String) As Boolean
Select Case mask
Case MaskType.Any
Return True
Case MaskType.[Integer]
If str = NumberFormatInfo.CurrentInfo.NegativeSign Then
Return True
End If
Exit Select
Case MaskType.[Decimal]
If str = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator OrElse str = NumberFormatInfo.CurrentInfo.NegativeSign Then
Return True
End If
Exit Select
End Select
If mask.Equals(MaskType.[Integer]) OrElse mask.Equals(MaskType.[Decimal]) Then
For Each ch As Char In str
If Not [Char].IsDigit(ch) Then
Return False
End If
Next
Return True
End If
Return False
End Function
End Region
End Class
Public Enum MaskType
Any
[Integer]
[Decimal]
End Enum
End Namespace

Figured out the solution. I am testing the length of the text and making sure it is < the max length.
If Not textInserted Then
If _this.Text.Length < _this.MaxLength Then
text = text.Substring(0, caret) & Convert.ToString(e.Text) & (If((caret < _this.Text.Length), text.Substring(caret), String.Empty))
caret += 1
End If
End If
Used this on the integer function.

Related

How to implement lazy loading in listview wpf VB.net

I'm newbie, I've a XAML file and code behind's, its load all data but I will lazy loading. I binding data in listview. I tried searching but did not produce the expected results, so there is no way that can be done.
code behind:
Public Sub MappingThumbnailSearchResult(thumbSearchResult As VI_ThumbnailSearchResultResponse, token As CancellationToken, ByRef dataDic As Dictionary(Of String, ObservableCollection(Of Object)))
Dim data As List(Of Object) = New List(Of Object)
Try
If thumbSearchResult.result_body Is Nothing OrElse thumbSearchResult.result_body.search_result Is Nothing Then Exit Sub
For Each item In thumbSearchResult.result_body.search_result
Try
If token.IsCancellationRequested Then Exit Sub
Dim thumbnailKey As String = ""
If Not item.thumbnail_key.Contains("\\") Then
thumbnailKey = item.thumbnail_key.ToString().Replace("\", "\\")
Else
thumbnailKey = item.thumbnail_key
End If
Dim imageResult = RequestAPI.GetInstance.GetThumbnailBase64(New VI_ThumbnailRequest With {.ThumbnailKey = thumbnailKey})
Dim hasThumb As Boolean = False
If imageResult IsNot Nothing Then
If imageResult.result_body.thumbnail IsNot Nothing Then
hasThumb = True
Dim base64Str As String = imageResult.result_body.thumbnail
item.thumbnail_base64 = imageResult.result_body.thumbnail
item.thumbnail_bitmap = BaseViewModel.BitmapFromSource(BaseViewModel.Base64ToImage(base64Str))
End If
End If
If Not hasThumb Then
'default image if have error when get thumbnail image
If item.system_type.Equals(EnumType.SystemType.face.ToString()) Then
item.thumbnail_base64 = BaseViewModel.ConvertBitmapToBase64(My.Resources.gender_unknown_2)
item.thumbnail_bitmap = My.Resources.gender_unknown_2
ElseIf item.system_type.Equals(EnumType.SystemType.people.ToString()) Then
item.thumbnail_base64 = BaseViewModel.ConvertBitmapToBase64(My.Resources.People)
item.thumbnail_bitmap = My.Resources.People
End If
End If
Dim tmpDate As DateTime
Dim shotDate As Date
If DateTime.TryParseExact(item.shot_date_time, RESPONSE_DATE_FORMAT2, Nothing, DateTimeStyles.AssumeLocal, tmpDate) Then
shotDate = tmpDate
Else
shotDate = DateTime.Now
End If
Dim dateKey As String = shotDate.ToString(PRIVATE_DATE_FORMAT)
If Not dataDic.ContainsKey(dateKey) Then
Dim thumbList = New ObservableCollection(Of Object)
Dim objThumb As Object = MappingVIThumbnailFromResponse(item, shotDate)
thumbList.Add(objThumb)
dataDic.Add(dateKey, thumbList)
Else
Dim objThumb As Object = MappingVIThumbnailFromResponse(item, shotDate)
dataDic.Item(dateKey).Add(objThumb)
End If
Catch ex As Exception
Dim b As Integer = 0
End Try
Next
Catch ex As Exception
Dim c As Integer = 0
End Try
End Sub
After, I binding data as below
Dim result As ObservableCollection(Of ListViewThumbnailViewModel) = New ObservableCollection(Of ListViewThumbnailViewModel)
If dataDic.Count > 0 Then
If token.IsCancellationRequested Then Return data
For Each pair As KeyValuePair(Of String, ObservableCollection(Of Object)) In dataDic
Dim _date As DateTime = DateTime.ParseExact(pair.Key, PRIVATE_DATE_FORMAT, CultureInfo.InvariantCulture)
result.Add(New ListViewThumbnailViewModel() With {.DateItem = _date, .ListThumbnail = pair.Value})
_viewModel.ResultSearch.TotalData += pair.Value.Count
Next
_viewModel.ResultSearch.ListResult = result
_viewModel.ResultSearch.ListResultActual = result
_viewModel.ResultSearch.PageSize = PageHelper.GetPageSizeWithZoom(_viewModel.ResultSearch.ZoomImage * 10, _viewModel.ResultSearch.PageSizeStart, _viewModel.ResultSearch.NumberChange)
_viewModel.ResultSearch.PageCurrent = 0
_viewModel.ResultSearch.TotalPage = PageHelper.GetTotalPageByPageSize(result.Count, _viewModel.ResultSearch.PageSize)
Else
_viewModel.ResultSearch.ListResult = Nothing
_viewModel.ResultSearch.ListResultActual = Nothing
End If
Catch ex As Exception
Throw New AIMatchingException(ex)
End Try
Return data
What should I do? please help me, thanks!!!

BackgroundWorker.ReportProgress doesn't display changes in my UI

I have a compare button which starts a background worker.
Private Sub btnCompare_Click(sender As Object, e As EventArgs) Handles btnCompare.Click
m_ProgressBar = New ProgressBar
m_ProgressBar.Show()
m_ProgressBar.txtBlockMainProgress.Dispatcher.BeginInvoke(Sub()
m_ProgressBar.txtBlockMainProgress.Text = "Comparing excel file(s)... Please wait. This might take a while."
End Sub)
Me.backgroundWorker = New BackgroundWorker
Me.backgroundWorker.WorkerReportsProgress = True
Me.backgroundWorker.WorkerSupportsCancellation = True
AddHandler Me.backgroundWorker.DoWork, AddressOf worker_DoWork
AddHandler Me.backgroundWorker.ProgressChanged, AddressOf worker_ProgressChanged
AddHandler Me.backgroundWorker.RunWorkerCompleted, AddressOf worker_RunWorkerCompleted
Me.backgroundWorker.RunWorkerAsync()
TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Normal
End Sub
The DoWork Event of my backgroundworker initialize a class Compare that has a method named Compare which accept a backgroundworker as parameter
Private Sub worker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
blnCompareDone = True
objExcelCompare = New Compare
With objExcelCompare
.SetThreshold = dblThreshold
.CompareToBestMatchData = blnBestMatchFlg
.CompareMerge = blnCompareMerge
.CompareTextWrap = blnCompareTextWrap
.CompareTextAlign = blnCompareTextAlign
.CompareOrientation = blnCompareOrientation
.CompareBorder = blnCompareBorder
.CompareBackColor = blnCompareBackColor
.CompareFont = blnCompareFont
.NoOfPages = intNoOfPages
.Page_Location_1 = objLocation_1
.Page_Location_2 = objLocation_2
.RemovedColumn = objRemoveCol
.RemovedRow = objRemoveRow
.AddedColumn = objAddCol
.AddedRow = objAddRow
.DataChange = objChangeData
.Compare(objWorksheet_1, objWorksheet_2, Me.backgroundWorker, e)
objEquivalentColumns = .EquivalentColumns
objEquivalentRows = .EquivalentRows
objValueResult_1 = .ValueResult_1
objValueResult_2 = .ValueResult_2
objFormatResult = .FormatResult
End With
End Sub
Inside the compare method i use ReportProgress to update my UI after comparing each page of excel file. There are total of 2 pages so the updating of progress bar will be 50% then 100%.
Public Sub Compare(ByRef p_objWorkSheet_1 As Worksheet, ByRef p_objWorkSheet_2 As Worksheet, ByRef p_backgroundWorker As BackgroundWorker, ByRef e As System.ComponentModel.DoWorkEventArgs)
If p_objWorkSheet_1 Is Nothing OrElse p_objWorkSheet_2 Is Nothing Then
'Error when no instance on either worksheets was found
Throw New Exception("No instances of worksheet is found.")
Exit Sub
End If
'********************Start of Comparison*********************
objExcelData_1 = New Dictionary(Of Integer, Dictionary(Of Tuple(Of Integer, Integer), Range))
objExcelData_2 = New Dictionary(Of Integer, Dictionary(Of Tuple(Of Integer, Integer), Range))
objEquivalentColumns = New Dictionary(Of Integer, Dictionary(Of Integer, Integer))
objEquivalentRows = New Dictionary(Of Integer, Dictionary(Of Integer, Integer))
objValueResult_1 = New Dictionary(Of Integer, Dictionary(Of Tuple(Of Integer, Integer), List(Of ValueError)))
objValueResult_2 = New Dictionary(Of Integer, Dictionary(Of Tuple(Of Integer, Integer), List(Of ValueError)))
objFormatResult = New Dictionary(Of Integer, Dictionary(Of Tuple(Of Integer, Integer), List(Of FormatError)))
'Loop through all pages
For w_intCtr_1 As Integer = 1 To intNoOfPages
If p_backgroundWorker.CancellationPending = True Then
e.Cancel = True
Return
End If
Dim w_intCurrentStep As Integer = 1
GetExcelData(p_objWorkSheet_1, objExcelData_1, objLocation_1, w_intCtr_1)
GetExcelData(p_objWorkSheet_2, objExcelData_2, objLocation_2, w_intCtr_1)
If objExcelData_1 Is Nothing OrElse objExcelData_2 Is Nothing Then
'No data to compare
Exit Sub
End If
objCompareByData = New Compare_Data
'Compare value of excelsheets
With objCompareByData
'Set threshold, excel data, and location of page to compare
.SetThreshold = dblThreshold
.CompareToBestMatchData = blnBestMatchFlg
.SetExcelData_1 = objExcelData_1(w_intCtr_1)
.SetLocation_1 = objLocation_1(w_intCtr_1)
.SetExcelData_2 = objExcelData_2(w_intCtr_1)
.SetLocation_2 = objLocation_2(w_intCtr_1)
If objRemoveCol Is Nothing = False AndAlso objRemoveCol.ContainsKey(w_intCtr_1) Then
.SetRemovedColumn = objRemoveCol(w_intCtr_1)
End If
If objRemoveRow Is Nothing = False AndAlso objRemoveRow.ContainsKey(w_intCtr_1) Then
.SetRemovedRow = objRemoveRow(w_intCtr_1)
End If
If objAddCol Is Nothing = False AndAlso objAddCol.ContainsKey(w_intCtr_1) Then
.SetAddedColumn = objAddCol(w_intCtr_1)
End If
If objAddRow Is Nothing = False AndAlso objAddRow.ContainsKey(w_intCtr_1) Then
.SetAddedRow = objAddRow(w_intCtr_1)
End If
If objChangeData Is Nothing = False AndAlso objChangeData.ContainsKey(w_intCtr_1) Then
.SetDataChange = objChangeData(w_intCtr_1)
End If
If p_backgroundWorker.CancellationPending = True Then
e.Cancel = True
Return
End If
'Proceed to compare
.Compare()
objEquivalentColumns.Add(w_intCtr_1, .EquivalentColumns)
objEquivalentRows.Add(w_intCtr_1, .EquivalentRows)
objValueResult_1.Add(w_intCtr_1, .ExcelData_Result_1)
objValueResult_2.Add(w_intCtr_1, .ExcelData_Result_2)
End With
If blnCompareMerge OrElse blnCompareTextWrap OrElse blnCompareTextAlign OrElse blnCompareOrientation OrElse blnCompareBorder OrElse blnCompareBackColor OrElse blnCompareFont Then
objCompareByFormat = New Compare_Format
'Compare format of excelsheets
With objCompareByFormat
'Set excel data to compare
.SetExcelFormat_1 = objExcelData_1(w_intCtr_1)
.SetExcelFormat_2 = objExcelData_2(w_intCtr_1)
'Set equivalent columns of page retrieved from comparing values of both excel sheets
'Set equivalent rows of page retrieved from comparing values of both excel sheets
If objEquivalentColumns Is Nothing = False AndAlso objEquivalentColumns.ContainsKey(w_intCtr_1) Then
.SetEquivalentColumns = objEquivalentColumns(w_intCtr_1)
End If
If objEquivalentRows Is Nothing = False AndAlso objEquivalentRows.ContainsKey(w_intCtr_1) Then
.SetEquivalentRows = objEquivalentRows(w_intCtr_1)
End If
.CompareMerge = blnCompareMerge
.CompareTextWrap = blnCompareTextWrap
.CompareTextAlign = blnCompareTextAlign
.CompareOrientation = blnCompareOrientation
.CompareBorder = blnCompareBorder
.CompareBackColor = blnCompareBackColor
.CompareFont = blnCompareFont
If p_backgroundWorker.CancellationPending = True Then
e.Cancel = True
Return
End If
.Compare()
'Set comparison result of page to collection
objFormatResult.Add(w_intCtr_1, .ExcelFormat_Result)
End With
End If
If p_backgroundWorker.CancellationPending = True Then
e.Cancel = True
Return
End If
'Set result to excel sheets
AddValueResultToWorkSheet(p_objWorkSheet_1, p_objWorkSheet_2, w_intCtr_1)
If p_backgroundWorker.CancellationPending = True Then
e.Cancel = True
Return
End If
'Set result to excel sheets
AddFormatResultToWorkSheet(p_objWorkSheet_2, w_intCtr_1)
p_backgroundWorker.ReportProgress((100 / intNoOfPages) * w_intCtr_1, (100 / intNoOfPages) * w_intCtr_1 & "% Completed " & w_intCtr_1 & " out of " & intNoOfPages & " pages")
Thread.Sleep(3000)
Next
End Sub
It works fine if i put Thread.Sleep(3000) after every ReportProgress. This is my ProgressChanged event handler
Private Sub worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs)
m_ProgressBar.pbStatusMain.Dispatcher.BeginInvoke(Sub()
m_ProgressBar.pbStatusMain.IsIndeterminate = False
m_ProgressBar.pbStatusMain.Value = e.ProgressPercentage
End Sub)
m_ProgressBar.txtBlockMainProgress.Dispatcher.BeginInvoke(Sub()
m_ProgressBar.txtBlockMainProgress.Text = e.UserState
End Sub)
TaskbarItemInfo.ProgressValue = e.ProgressPercentage / 100
End Sub
I wonder why sometimes it work and sometimes it doesnt. Based on my research the UI thread is being flooded with message causing it to be unresponsive or I used ReportProgress to frequent which causing the UI thread to ignore the next request. What am i doing wrong? Why the changes doesnt apply in my UI?

VB.NET | Array of pictureboxes in panel: Object reference not set to an instance of an object

In the code below I am attempting to change the tag of an existing control that was created in the array 'pictureboxes(9, 9)'. When I try to do this, I get the error 'Object reference not set to an instance of an object.'. This is done in the checkdata sub, near the bottom of the code with the comment 'Object reference not set to an instance of an object.'.
The string that is passed through to the sub is a long string of numbers, and the pictureboxes are placed into a layoutpanel if that is helpful.
I understand what this error means, I am aware that pictureboxes(i, j) is = nothing when breakpointed; I just don't know how to fix it :s
Any help is greatly appreciated and hopefully I will be quick to answer any comments/answers.
Thank you
Imports System.Net.Sockets
Imports System.Threading
Imports System.Text
Imports System.Net
Public Class Form1
'0 as default tile, 1 as clicked, 3 as set mine (host perspective)
Dim tiles() As Integer = {0}
Public pictureboxes(9, 9) As PictureBox
Dim flagged() As Integer
Dim clicked As Integer()
Dim columns As Integer = 10
Dim rows As Integer = 10
Dim placedMinesCount As Integer = 0
Dim formattedTag As String()
Public turn As Boolean = False
Dim stringToSend As String
Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For i As Byte = 0 To 9
For j As Byte = 0 To 9
pictureboxes(i, j) = New PictureBox
pictureboxes(i, j).Height = 60
pictureboxes(i, j).Width = 60
pictureboxes(i, j).ImageLocation = "0.png"
pictureboxes(i, j).Tag = "0|" & i & ", " & j
AddHandler pictureboxes(i, j).Click, AddressOf Tile_Click
Dim column As Integer = j
Dim row As Integer = i
Panel.Controls.Add(pictureboxes(i, j), column, row)
Next
Next
If Login.isHost = True Then
Me.Text = "Set your mines (10)"
turn = True
ElseIf Login.isHost = False Then
Me.Text = "Await your turn"
btnEndTurn.Visible = False
btnEndTurn.Enabled = False
End If
End Sub
Protected Sub Tile_Click(ByVal sender As Object, ByVal e As EventArgs)
formatSenderTag(sender.tag)
If Login.isHost = True Then
Dim clickAction As String = formattedTag(0)
Select Case clickAction
Case "0"
If placedMinesCount < 10 Then
placedMinesCount = placedMinesCount + 1
sender.imagelocation = "3.png"
sender.tag = "3"
Me.Text = "Set your mines (" & 10 - placedMinesCount & ")"
ElseIf placedMinesCount >= 10 Then
MsgBox("You have placed all of your 10 Mines")
End If
Case "2"
MsgBox("You cannot set a mine here")
Case "3"
placedMinesCount = placedMinesCount - 1
Me.Text = "Set your mines (" & 10 - placedMinesCount & ")"
sender.imagelocation = "0.png"
sender.tag = "0"
End Select
ElseIf Login.isHost = False Then
Dim clickAction As String = formattedTag(0)
Select Case clickAction
Case "0"
sender.tag = "1"
sender.imagelocation = "1.png"
Case "3"
MsgBox("Game Over")
Case "2"
MsgBox("Already Clicked")
End Select
End If
End Sub
Private Sub formatSenderTag(ByVal sender As String)
'split into array
'element 0 as TILE TYPE
'element 1 as TILE LOCATION
formattedTag = sender.Split(New String() {"|"}, StringSplitOptions.None)
End Sub
Private Sub Form_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
End
End Sub
Private Sub btnEndTurn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEndTurn.Click
turn = False
gridtostring()
senddata()
End Sub
Private Sub gridtostring()
For i As Byte = 0 To 9
For j As Byte = 0 To 9
formatSenderTag(pictureboxes(i, j).Tag & "|")
stringToSend = stringToSend & formattedTag(0)
Next
Next
End Sub
Private Sub senddata()
'***SEND STUFF
'Assuming you have a textbox with the data you want to send
If (Not String.IsNullOrEmpty(stringToSend)) Then
Dim data() As Byte = Encoding.ASCII.GetBytes(stringToSend)
Login.sendingClient.Send(data, data.Length)
End If
End Sub
Public Sub checkdata(ByVal data As String)
If Not data = stringToSend Then
'Dim loopcount As Integer = 0
For i As Byte = 0 To 9
For j As Byte = 0 To 9
Dim loopcount As Integer = (i.ToString & j.ToString) + 1
'Dim pineapple As String = pictureboxes(i, j).Tag
'pictureboxes(i, j).Tag = GetChar(data, 3)
pictureboxes(i, j).Tag = GetChar(data, loopcount) & "|" & i & ", " & j '***Object reference not set to an instance of an object.***
formatSenderTag(pictureboxes(i, j).Tag)
pictureboxes(i, j).ImageLocation = formattedTag(0)
pictureboxes(i, j).ImageLocation = "0.png"
'Panel.Controls(pictureboxes(i, j).Tag) = GetChar(data, 3) '.Tag = GetChar(data, 3)
Next
Next
End If
End Sub
End Class
***AND BELOW IS THE OTHER FORM WHICH CALLS CHECKDATA()
Imports System.Net.Sockets
Imports System.Threading
Imports System.Text
Imports System.Net
Public Class Login
Dim Port As Integer = 8123
Private Const broadcastAddress As String = "255.255.255.255"
Public receivingClient As UdpClient
Public sendingClient As UdpClient
Dim sendAddress As String
Dim ServerMode As Boolean = False
Public isHost As Boolean = true
Dim returndata As String
Private Sub Login_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub ComboWANLAN_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboWANLAN.SelectedIndexChanged
If ComboWANLAN.Text = "Online (WAN)" Then
txtSendAddress.Enabled = True
ElseIf ComboWANLAN.Text = "Offline (LAN)" Then
txtSendAddress.Enabled = False
End If
End Sub
Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
'***START PORT LISTENING/SENDING AND NETWORKING STUFFS
Port = txtPort.Text
InitializeSender()
InitializeReceiver()
End Sub
Private Sub btnHost_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHost.Click
'***START PORT LISTENING/SENDING AND NETWORKING STUFFS
Port = txtPort.Text
InitializeSender()
InitializeReceiver()
isHost = True
Me.Hide()
Form1.Show()
End Sub
Private Sub InitializeSender()
If ComboWANLAN.Text = "Offline (LAN)" Then
sendingClient = New UdpClient(broadcastAddress, Port)
'Use broadcastAddress for sending data locally (on LAN), otherwise you'll need the public (or global) IP address of the machine that you want to send your data to
ElseIf ComboWANLAN.Text = "Online (WAN)" Then
sendAddress = txtSendAddress.Text
sendingClient = New UdpClient(sendAddress, Port)
'Use broadcastAddress for sending data locally (on LAN), otherwise you'll need the public (or global) IP address of the machine that you want to send your data to
End If
sendingClient.EnableBroadcast = True
End Sub
Private Sub InitializeReceiver()
receivingClient = New UdpClient(Port)
ThreadPool.QueueUserWorkItem(AddressOf Receiver) 'Start listener on another thread
End Sub
Private Sub Receiver()
Dim endPoint As IPEndPoint = New IPEndPoint(IPAddress.Any, port) 'Listen for incoming data from any IP on the specified port
Do While True 'Notice that i've setup an infinite loop to continually listen for incoming data
Dim data() As Byte
data = receivingClient.Receive(endPoint)
If Form1.turn = False Then
returndata = Encoding.ASCII.GetString(data) 'Recived data as string
Form1.checkdata(returndata)
End If
Loop
End Sub
Private Sub Form_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
End
End Sub
End Class
***STACK TRACE
at Minesweeper.Form1.checkdata(String data) in c:\users\harry\documents\visual studio 2010\Projects\Minesweeper\Minesweeper\Form1.vb:line 139
at Minesweeper.Login.Receiver() in C:\Users\Harry\Documents\Visual Studio 2010\Projects\Minesweeper\Minesweeper\Login.vb:line 71
at Minesweeper.Login._Lambda$__1(Object a0) in C:\Users\Harry\Documents\Visual Studio 2010\Projects\Minesweeper\Minesweeper\Login.vb:line 61
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
Note: Screwed up with the spacings in some places
This code does not give an error with the data you gave:
checkdata("00000000000000000000000000000000000000000000000000000000000000000000000000000000‌​00000000000000000000")
Public Sub checkdata(ByVal data As String)
If Not data = stringToSend Then
'Dim loopcount As Integer = 0
For i As Byte = 0 To 9
For j As Byte = 0 To 9
Dim loopcount As Integer = (i.ToString & j.ToString) + 1
'Dim pineapple As String = pictureboxes(i, j).Tag
'pictureboxes(i, j).Tag = GetChar(data, 3)
pictureboxes(i, j).Tag = GetChar(data, loopcount) & "|" & i & ", " & j '***Object reference not set to an instance of an object.***
formatSenderTag(pictureboxes(i, j).Tag)
pictureboxes(i, j).ImageLocation = formattedTag(0)
pictureboxes(i, j).ImageLocation = "0.png"
'Panel.Controls(pictureboxes(i, j).Tag) = GetChar(data, 3) '.Tag = GetChar(data, 3)
Next
Next
End If
End Sub
Looking at your stack trace and code, you are missing the instantiation of Form1 in your login class. I think this can be the problem.
Try adding this to the beginning of your Login class:
Dim Form1 as New Form1

Winforms (Horizontal) Scrollbar Unexplained Behavior

When I resize my form with the resize handle on the bottom right corner of the form, it fires the sizechanged event of my user control. Inside the user control I have code to set the maximum and value of the horizontal scroll bar.
If I resize to the right, the code works as expected. When I resize to the left, the scrolling thumb gets really big and scrolling does not work as expected. It's as if the Maximum got set to a low number, but my Debug.WriteLine shows that this is not the case. Actually, as I slowly resize the form to be narrower, it quickly toggles between doing it right and doing it wrong.
I deal with scroll bars rarely and when I do they are always a pain. Is there a ScrollBar guru who knows why this is happening? I googled it and searched SO too, but I really don't know what to search on.
Here is my code. The relevant part is what is called from the sizechanged event handler, which is almost to the bottom of the code.
Imports System.Reflection
Public Class Grid
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint Or ControlStyles.DoubleBuffer, True) 'Or ControlStyles.ResizeRedraw
End Sub
Private _FirstVisibleRow As Row
Private Property FirstVisibleRow As Row
Get
If _FirstVisibleRow Is Nothing And Rows.Any Then
_FirstVisibleRow = Rows.First
End If
Return _FirstVisibleRow
End Get
Set(value As Row)
_FirstVisibleRow = value
LastVisibleRow = GetLastVisibleRow()
End Set
End Property
Private _HeaderRow As Row
Public Property HeaderRow As Row
Get
If _HeaderRow Is Nothing Then
_HeaderRow = New Row(Me, RowHeight)
For Each Column As Column In Columns
_HeaderRow.Cells.Add(New Cell(Column, _HeaderRow))
Next
End If
Return _HeaderRow
End Get
Private Set(value As Row)
_HeaderRow = value
End Set
End Property
Private _LastVisibleRow As Row
Private Property LastVisibleRow As Row
Get
If _LastVisibleRow Is Nothing Then
_LastVisibleRow = GetLastVisibleRow()
End If
Return _LastVisibleRow
End Get
Set(value As Row)
_LastVisibleRow = value
End Set
End Property
Private _TotalColumnWidth As Integer
Friend Property TotalColumnWidth As Integer
Get
If _TotalColumnWidth = Nothing Then
_TotalColumnWidth = GetTotalColumnWidth()
End If
Return _TotalColumnWidth
End Get
Set(value As Integer)
_TotalColumnWidth = value
SetScrollBarVisibility()
End Set
End Property
Private _TotalRowHeight As Integer
Friend Property TotalRowHeight As Integer
Get
If _TotalRowHeight = Nothing Then
_TotalRowHeight = GetTotalRowHeight()
End If
Return _TotalRowHeight
End Get
Set(value As Integer)
_TotalRowHeight = value
SetScrollBarVisibility()
End Set
End Property
Private _VisibleGridSize As Size
Private Property VisibleGridSize As Size
Get
If _VisibleGridSize = Nothing Then
_VisibleGridSize = GetVisibleGridSize()
End If
Return _VisibleGridSize
End Get
Set(value As Size)
_VisibleGridSize = value
VisibleRowCount = GetVisibleRowCount()
SetScrollBarVisibility()
End Set
End Property
Private Sub SetScrollBarVisibility()
VScrollBar1.Bounds = New Rectangle(Width - VScrollBar1.Width, 0, VScrollBar1.Width, Height - IIf(HScrollBar1.Visible, HScrollBar1.Height, 0))
HScrollBar1.Bounds = New Rectangle(0, Height - HScrollBar1.Height, Width - IIf(VScrollBar1.Visible, VScrollBar1.Width, 0), HScrollBar1.Height)
VScrollBar1.Maximum = Math.Max(0, TotalRowHeight - Height - IIf(HScrollBar1.Visible, HScrollBar1.Height, 0))
HScrollBar1.Maximum = Math.Max(0, TotalColumnWidth - Width + IIf(VScrollBar1.Visible, VScrollBar1.Width, 0))
HScrollBar1.Value = 0
VScrollBar1.Visible = TotalRowHeight > VisibleGridSize.Height
HScrollBar1.Visible = TotalColumnWidth > VisibleGridSize.Width
Debug.WriteLine(String.Format("HScrollBar1.Minimum {0}, HScrollBar1.Maximum {1}, HScrollBar1.Value {2}", HScrollBar1.Minimum, HScrollBar1.Maximum, HScrollBar1.Value))
End Sub
Private _VisibleRowCount As Integer
Private Property VisibleRowCount As Integer
Get
If _VisibleRowCount = 0 Then
_VisibleRowCount = GetVisibleRowCount()
End If
Return _VisibleRowCount
End Get
Set(value As Integer)
_VisibleRowCount = value
LastVisibleRow = GetLastVisibleRow()
PageHeight = GetPageHeight()
End Set
End Property
Private Function GetLastVisibleRow() As Row
If Not Rows.Any Then Return Nothing
Return Rows(Math.Min(FirstVisibleRow.Index + VisibleRowCount - 1, Rows.Count - 1))
End Function
Private Function GetPageHeight() As Integer
Return RowHeight * GetVisibleRowCount()
End Function
Private Function GetRowHeight() As Integer
Return TextRenderer.MeasureText("X", Font).Height + 6
End Function
Private Function GetVisibleGridSize() As Size
Return New Size(Width - IIf(VScrollBar1.Visible, VScrollBar1.Width, 0),
Height - HeaderRow.Height - IIf(HScrollBar1.Visible, HScrollBar1.Height, 0)) 'don't count header row or horiz scroll bar
End Function
Private Function GetVisibleRowCount() As Integer
Return Math.Ceiling(VisibleGridSize.Height / RowHeight)
End Function
Public Shadows Sub Refresh()
ClearSelection()
_HeaderRow = Nothing
_Rows = Nothing
AutoSizeColumns()
TotalRowHeight = GetTotalRowHeight()
Invalidate()
End Sub
Friend Function GetTotalColumnWidth() As Integer
Return Columns.Select(Function(x) x.Width).Aggregate(0, Function(x, y) x + y)
End Function
Friend Function GetTotalRowHeight() As Integer
Return Rows.Select(Function(x) x.Height).Aggregate(0, Function(x, y) x + y)
End Function
Private Function VisibleRows() As List(Of Row)
Return Rows.Where(Function(x) x.Index >= FirstVisibleRow.Index AndAlso x.Index <= LastVisibleRow.Index).ToList
End Function
Private Sub Grid_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
e.Graphics.Clear(BackColor)
'e.ClipRectangle
Dim Left As Integer = -HScrollBar1.Value
For Each Column As Column In Columns
Left = Column.Draw(e.Graphics, Left)
Next
Dim Top As Integer = HeaderRow.Draw(e.Graphics)
For Each Row As Row In VisibleRows()
Top = Row.Draw(e.Graphics, Top)
Next
End Sub
Private Sub Grid_Scroll(sender As Object, e As System.Windows.Forms.ScrollEventArgs) Handles Me.Scroll
If e.ScrollOrientation = ScrollOrientation.VerticalScroll Then
Select Case e.Type
Case ScrollEventType.First
FirstVisibleRow = Rows.First
Case ScrollEventType.Last
FirstVisibleRow = Rows(Rows.Last.Index - VisibleRowCount + 1)
Case ScrollEventType.SmallDecrement
FirstVisibleRow = Rows(Math.Max(FirstVisibleRow.Index - 1, 0))
Case ScrollEventType.SmallIncrement
FirstVisibleRow = Rows(Math.Min(FirstVisibleRow.Index + 1, Rows.Last.Index - VisibleRowCount + 1))
Case ScrollEventType.LargeDecrement
FirstVisibleRow = Rows(Math.Max(FirstVisibleRow.Index - VisibleRowCount, 0))
Case ScrollEventType.LargeIncrement
FirstVisibleRow = Rows(Math.Min(LastVisibleRow.Index, Rows.Last.Index - VisibleRowCount + 1))
End Select
End If
Invalidate()
End Sub
Private Sub Grid_SizeChanged(sender As Object, e As System.EventArgs) Handles Me.SizeChanged
VisibleGridSize = GetVisibleGridSize()
End Sub
Private Sub HScrollBar1_Scroll(sender As Object, e As System.Windows.Forms.ScrollEventArgs) Handles HScrollBar1.Scroll
Invalidate()
End Sub
End Class
The AutoScroll property of my UserControl was getting set to True by a parent control. Once I set it back to False in the designer, my code works as expected 100% of the time.

Two Dimensional Array VB

Ok so I am having problems adding elements into my 2d array. I am using 3 textboxes to allow a user to input items into my array. My problem is I cant seem to get the array to go past (0,2). I want the user to be able to add a row of inputs with each click of the add button. This is so far what I have in my code. Can anyone help? This is not for a class I am learning on my own.
Option Strict On
Option Explicit On
Option Infer Off
Public Class Form1
Private strExams(49, 2) As String
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
Dim strStudent As String = txtStudent.Text
Dim strTest As String = txtTest.Text
Dim strScore As String = txtScore.Text
Dim count As Integer = 0
If count <= 49 Then
strExams(count, 0) = strStudent
strExams(count, 1) = strTest
strExams(count, 2) = strScore
count += 1
End If
txtStudent.Text = String.Empty
txtTest.Text = String.Empty
txtScore.Text = String.Empty
txtStudent.Focus()
End Sub
Try this... Your count variable must be placed outside the btnAdd_Click sub or it will always reset back to 0, thus, you won't get past (0,2).
Option Strict On
Option Explicit On
Option Infer Off
Public Class Form1
Private strExams(49, 2) As String
Dim count As Integer = 0
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
Dim strStudent As String = txtStudent.Text
Dim strTest As String = txtTest.Text
Dim strScore As String = txtScore.Text
If count <= 49 Then
strExams(count, 0) = strStudent
strExams(count, 1) = strTest
strExams(count, 2) = strScore
count += 1
End If
txtStudent.Text = String.Empty
txtTest.Text = String.Empty
txtScore.Text = String.Empty
txtStudent.Focus()
End Sub

Resources