Reference to a element inside a grid in wpf - wpf

I have a function which querys the database for Strings (which are x:Name="" in my application)
Following is the code:
Try
For Each s In output
Dim nameOfControl = s
Dim window = Windows.Application.Current.Windows(0)
Dim visuals = GetVisualChildren(Of FrameworkElement)(window)
Dim child = visuals.OfType(Of FrameworkElement)().FirstOrDefault(Function(x) x.Name = nameOfControl)
child.Visibility = Visibility.Collapsed
Next
Public Iterator Function GetVisualChildren(Of T As Visual)(parent As DependencyObject) As IEnumerable(Of T)
Dim child As T = Nothing
Dim numVisuals As Integer = VisualTreeHelper.GetChildrenCount(parent)
For i As Integer = 0 To numVisuals - 1
Dim v As Visual = DirectCast(VisualTreeHelper.GetChild(parent, i), Visual)
child = TryCast(v, T)
If v IsNot Nothing Then
For Each item In GetVisualChildren(Of T)(v)
Yield item
Next
End If
If child IsNot Nothing Then
Yield child
End If
Next
End Function
I cannot seem to figure out why this does not work for all elements, ie. my window consists of a TabControl which i can call by "x name", same goes for toolBar, everything works well even with TabItem's but i cannot reference to <Button x:Name="buttonRefresh" which is inside one of TabItem's grids.
I recieve a error NullReferenceException on line bellow:
child.Visibility = Visibility.Collapsed
If i insert a breakpoint at that line i get this {System.Windows.Controls.TabItem Header:FirstTab Content:} for child so i'm asuming i need to change something about this piece of code
Dim window = Windows.Application.Current.Windows(0)

Your problem is here:
Dim child = visuals.OfType(Of FrameworkElement)().FirstOrDefault(Function(x) x.Name = nameOfControl)
The FirstOrDefault method will return Nothing if the predicate results in False. In your case, it has done so because on the next line, child is null, hence the NRE:
child.Visibility = Visibility.Collapsed
You can't assign to the Visibility property on child because it's Nothing.
Your predicate is Function(x) x.Name = nameOfControl, so there must not be a value in the collection returned by visuals.OfType(Of FrameworkElement)() whose Name property equals nameOfControl.
To address this, you need to debug it and see what's really going on. I would break your statement into two lines:
Dim child = visuals.OfType(Of FrameworkElement)()
Dim match = child.FirstOrDefault(Function(x) x.Name = nameOfControl)
Put a break point on the second line so it breaks before that statement runs. Then look in your locals/autos window (assuming Visual Studio), and see what's actually in the collection.
One other thing to note here: when you compare x.Name to nameOfControl with the equals sign =, it does so in case sensitive manner, so if you have MyName and myname, those two are not equal. You can use this instead if you want it to be compare in a case-insensitive manner:
Function(x) x.Name.Equals(nameOfControl, StringComparison.CurrentCultureIgnoreCase)

Related

Is there a datagrid mouse down hit test to get the row and column index of the click?

With Winforms' DataGridView, one could use HitTest to determine the column and row index of the mouse down (and other events).
Dim hti As DataGridView.HitTestInfo = sender.HitTest(e.X, e.Y)
Is there something similar with WPF's DataGrid? I need to get the row and column indexes for the MouseLeftButtonDown event.
It's a bit more complicated than this but the following links should be helpful in getting the index of the row and column.
WPF DataGrid - detecting the column, cell and row that has been clicked: http://blog.scottlogic.com/2008/12/02/wpf-datagrid-detecting-clicked-cell-and-row.html
WPF DataGrid - get row number which mouse cursor is on
You will have to use the VisualTreeHelper class to traverse the Visual elements that make up the DataGrid as explained above.
For those that may wish to avoid my search here is the total code I ended up puzzling together that is able to deliver:
Current row index
Current Column index
Current Column header And
is able to expose the value/s of columns on the row.
The code goes into MouseLeftButtonup event and DGrid1 is the name of the grid
Dim currentRowIndex As Integer = -1
Dim CurrentColumnIndex As Integer = -1
Dim CurrentColumnHeader As String = ""
Dim Myrow As DataRowView = Nothing
Dim dep As DependencyObject = DirectCast(e.OriginalSource, DependencyObject)
While dep IsNot Nothing And Not TypeOf dep Is DataGridCell And Not TypeOf dep Is Primitives.DataGridColumnHeader
dep = VisualTreeHelper.GetParent(dep)
If dep IsNot Nothing Then
If TypeOf dep Is DataGridCell Then
Dim cell As DataGridCell = DirectCast(dep, DataGridCell)
Dim col As DataGridBoundColumn = DirectCast(cell.Column, DataGridBoundColumn)
Myrow = DGrid1.SelectedItem
CurrentColumnHeader = col.Header.ToString
CurrentColumnIndex = col.DisplayIndex
currentRowIndex = DGrid1.Items.IndexOf(DGrid1.CurrentItem)
Exit While
End If
End If
End While
If currentRowIndex = -1 OrElse CurrentColumnIndex = -1 OrElse CurrentColumnHeader = "" OrElse Myrow Is Nothing Then Exit Sub
'code to consume the variables from here
Dim strinwar As String = Myrow.Item("header name or index").ToString()

Datagridviewcell Tooltip doesn't display after modifying image of any cell

In my winforms application, I loop through the cells of a datagridview and add a tooltip for specific cells based on values in other columns. I do this in the cellformatting event handler, and it worked perfectly. Here is the code:
Private Sub dgvResults_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles dgvResults.CellFormatting
Select Case dgvResults.Columns(e.ColumnIndex).Name
Case "TradeInValue"
DirectCast(dgvResults.Rows(e.RowIndex).Cells("TradeInValue"), DataGridViewTextBoxCell).ToolTipText = "Min = " & CDec(dgvResults.Item("BB_Min", e.RowIndex).FormattedValue).ToString("$#####.##") & ", Max = " & CDec(dgvResults.Item("BB_Max", e.RowIndex).FormattedValue).ToString("$#####.##")
If Not IsNothing(dgvResults.Item("SelectedTrimIndex", e.RowIndex).FormattedValue) AndAlso dgvResults.Item("SelectedTrimIndex", e.RowIndex).FormattedValue.ToString.Trim.Length > 0 AndAlso CInt(dgvResults.Item("SelectedTrimIndex", e.RowIndex).FormattedValue.ToString) <> -1 Then
If dgvResults.Item("ValueList", e.RowIndex).FormattedValue.ToString.Length > 0 Then
Dim ValueParts() As String = dgvResults.Item("ValueList", e.RowIndex).FormattedValue.ToString.Split("|")
'Dim selectedTrim As String = ValueParts(dgvResults.Item("SelectedTrimIndex", e.RowIndex).FormattedValue)
End If
End If
End Select
End Sub
Then, I added code in the cellpainting event handler to hide specific images, again based on values in the datagridview. Here is that code.
Private Sub dgvResults_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles dgvResults.CellPainting
If e.ColumnIndex >= 0 AndAlso e.RowIndex >= 0 Then
Select Case dgvResults.Columns(e.ColumnIndex).Name
Case "VIN_Pic"
If dgvResults.Rows(e.RowIndex).Cells("VIN_Value").FormattedValue = "" Then
DirectCast(dgvResults.Item(e.ColumnIndex, e.RowIndex), DataGridViewImageCell).Value = New Bitmap(1, 1)
End If
Case "EmailDisplayImage"
If dgvResults.Rows(e.RowIndex).Cells("ListingContactEmail").FormattedValue = "" Then
DirectCast(dgvResults.Item(e.ColumnIndex, e.RowIndex), DataGridViewImageCell).Value = New Bitmap(1, 1)
End If
End Select
End If
End Sub
When this code as added, the tooltips no longer display. The CellToolTipTextNeeded event fires, and it shows the correct text in the argument, but it never displays. Comment out the lines that assign a new image to the datagridviewimagecells, and the tooltips start displaying again.
I hope this explanation was sufficient. Any ideas?
With the below code, you will run into memory and GDI object leaks very easily as a new Bitmap instance is created every time the cell is painted. Also this is causing your ToolTip to be not displayed.
DirectCast(dgvResults.Item(e.ColumnIndex, e.RowIndex), DataGridViewImageCell).Value = New Bitmap(1, 1)
Define the empty bitmap in class level or add as embedded resource and use it.
Dim emptyBitmap As New Bitmap(1, 1);
DirectCast(dgvResults.Item(e.ColumnIndex, e.RowIndex), DataGridViewImageCell).Value = emptyBitmap

how to observe changes in an array in vb .net

i have an array A, i just want to monitor the changes in that array, return the changed position of that array.
myOldTextBox = myTextBox
myTextBox = New TextBox() {TextBox1, TextBox2, TextBox3, TextBox4, TextBox5}
Dim i As Integer
For i = 0 To myTextBox.Length - 1
If myTextBox(i).Text <> myOldTextBox(i).Text Then
Dim fs As Integer
fs = farray.Length
farray(fs) = i
End If
Next i
i am newbie in vb .net. Thank you.
I don't believe you can do that.
For a regular variable I would suggest using get/set.
For an array, I would suggest creating a method to update the values, instead of setting the values directly (you can enforce this by making the array private and only giving it access through a get and set method).
In that method you can then do anything you want.
Pseudo code:
private _array
Public Function GetArray(ByVal key As String) As String
return _array(key)
End Function
Public Function SetArray(ByVal key As String, ByVal val As String) as String
_array(key) = val
return val;
End Function
add a listbox, and whenever the if condition is satisfied, add content to the listbox
myTextBox = New TextBox() {TextBox1, TextBox2, TextBox3, TextBox4, TextBox5}
Dim i As Integer
For i = 0 To myTextBox.Length - 1
If myTextBox(i).Text <> myOldTextBox(i).Text Then
Dim fs As Integer
fs = farray.Length
farray(fs) = i
Listbox1.items.add(Format(now,"yyyy-MM-dd hh:mm:ss") & _
" array number changed: " & i
End If
Next i
EDITED: (Didn't notice you were doing what I posted)
I would change the For loop to a Do While loop, because I have found issues when comparing substring in a For Loop, try it and see if that doesn't fix your problem...
(I've even tried Microsoft code that failed in for Loops w/ substrings)
Also, I'd HIGHLY suggest you use a MessageBox.Show(sMsg) or Debug.WriteLine(sMsg) to ENSURE that data is correct...

Specified element is already the logical child of another element. Disconnect it first. After Removal

First off here is what i am trying to do: I need to dynamically reverse the order of the items in one stack panel and add them in the reverse order in a second. Here is the code that i am using:
Dim cp As ContentPresenter = TryCast(Utilities.GetDescendantFromName(TitleLegend, "ContentPresenter"), ContentPresenter)
If cp IsNot Nothing Then
Dim sp As StackPanel = TryCast(cp.Content, StackPanel)
If sp IsNot Nothing Then
Dim nsp As New StackPanel() With {.Orientation = System.Windows.Controls.Orientation.Vertical}
Dim count As Integer = sp.Children.Count
For i As Integer = count - 1 To 0 Step -1
Dim cc As ContentControl = TryCast(sp.Children(i), ContentControl)
If cc IsNot Nothing Then
sp.Children.Remove(cc)
nsp.Children.Add(cc)
End If
Next
cp.Content = Nothing
cp.Content = nsp
End If
End If
it runs through this code fine but right before the User Control loads i receive the error. I have looked around here and the solution that seems to work is removing the child from the first collection which i already do. Any help would be appreciated. Thank you
this is the solution that i used to solve my problem in case anyone else runs into this situation
Dim cp As ContentPresenter = TryCast(Utilities.GetDescendantFromName(TitleLegend, "ContentPresenter"), ContentPresenter)
If cp IsNot Nothing Then
Dim sp As StackPanel = TryCast(cp.Content, StackPanel)
If sp IsNot Nothing Then
If tempList Is Nothing Then
tempList = New List(Of ContentControl)
End If
Dispatcher.BeginInvoke(New Action(Function()
Dim count As Integer = sp.Children.Count
For i As Integer = count - 1 To 0 Step -1
Dim cc As ContentControl = TryCast(sp.Children(i), ContentControl)
sp.Children.Remove(TryCast(sp.Children(i), ContentControl))
If cc IsNot Nothing Then
tempList.Add(cc)
End If
Next
For i As Integer = count - 1 To 0 Step -1
Dim cc As ContentControl = TryCast(tempList(0), ContentControl)
tempList.Remove(TryCast(tempList(0), ContentControl))
If cc IsNot Nothing Then
sp.Children.Add(cc)
End If
Next
End Function), System.Windows.Threading.DispatcherPriority.Background, Nothing)
End If
End If

Customizing the columns in a bound grid control?

When I bind to the GridControl I want to get rid of columns showing something like:
System.Data.Objects.DataClasses.EntityCollection``1[Model.PersonEmails]
Instead I would like in this case to get the total number of emails based on the parent entity.
Sorry for the delay
I've already found a solution using the GridView1_CustomColumnDisplayText event handler.
Yes, it's third party control.
Private Sub GridView1_CustomColumnDisplayText(sender As Object, e As DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs) Handles GridView1.CustomColumnDisplayText
If e.Column.FieldName = "PersonEmails" Then
Dim Entities = DirectCast(e.Value, System.Data.Objects.DataClasses.EntityCollection(Of PersonEmails))
If Not Entities Is Nothing Then
If Entities.Count = 1 Then
Dim x As PersonEmail = Entities.FirstOrDefault()
e.DisplayText = x.Email
Else
e.DisplayText = Entities.Count
End If
End If
End If
End Sub

Resources