Datagrid text search - wpf

I want to search a text in the datagrid, A code written like below gives error
For i As Integer = 0 To _dt.Items.Count - 1
Dim row As DataGridRow = DirectCast(_dt.ItemContainerGenerator.ContainerFromIndex(i), DataGridRow)
For j As Integer = 0 To _dt.Columns.Count - 1
If row IsNot Nothing Then
Dim cellContent As TextBlock = TryCast(_dt.Columns(j).GetCellContent(row), TextBlock)
If cellContent IsNot Nothing AndAlso cellContent.Text.Equals(txtfind.Text) Then
_dt.ScrollIntoView(row, _dt.Columns(j))
Dim presenter As DataGridCellsPresenter = GetVisualChild(Of DataGridCellsPresenter(row))
Dim cell As DataGridCell = DirectCast(presenter.ItemContainerGenerator.ContainerFromIndex(j), DataGridCell)
_dt.SelectedItem = cell
cell.IsSelected = True
row.MoveFocus(New TraversalRequest(FocusNavigationDirection.[Next]))
Exit For
End If
End If
Next
Next
Error is for row : Array bounds cannot appear in type specifiers.
Statement: Dim presenter As DataGridCellsPresenter = GetVisualChild(Of DataGridCellsPresenter(row))
Help appreciated
abhimoh

Change:
Dim presenter As DataGridCellsPresenter = GetVisualChild(Of DataGridCellsPresenter(row))
'you have created an array with row number of values.
to:
Dim presenter As DataGridCellsPresenter = GetVisualChild(Of DataGridCellsPresenter)(row)

Related

WPF Dynamic image generation and printing is not working

In an application I'm developing, the user can select a number of items (max. 6) in a datagrid. These items should then be printed in a matrix style on pre-printed forms (see it like CD labels, 6 on a page).
I'm generating these images dynamically containing the selected content from a database. I then put these in a grid so they can be printed on the pre-printed forms.
I have the following code that creates the grid, generates the images from a user control and adds them to the grid and then prints these images.
I'm not following the MVVM pattern for the printing action. I created a reference to my view model in my code-behind.
Private Sub PrintButton_Click(sender As Object, e As RoutedEventArgs) Handles ButtonPrint.Click
Dim dlg As New PrintDialog
dlg.PrintTicket.PageMediaSize = New PageMediaSize(PageMediaSizeName.ISOA4)
Dim pageWidth As Double = GetPageWidth(dlg)
'Since the label is a perfect square: labelWidth = labelHeight
Dim labelWidthInPx As Integer = Utilities.ConvertMmToPixels(My.Settings.LabelWidthInMm)
'Set spacing distances in pixels
Dim horizontalLabelSpacing As Integer = Utilities.ConvertMmToPixels(My.Settings.HorizontalLabelSpacinginMm)
Dim verticalLabelSpacing As Integer = Utilities.ConvertMmToPixels(My.Settings.VerticalLabelSpacingInMm)
Dim topMargin As Integer = Utilities.ConvertMmToPixels(My.Settings.TopMarginInMm)
Dim leftMargin As Integer = Utilities.ConvertMmToPixels(My.Settings.LeftMarginInMm)
Dim bottomMargin As Integer = Utilities.ConvertMmToPixels(My.Settings.BottomMarginInMm)
'Create the table/grid
Dim tbl As New Grid
If CheckBoxPrintGridLines.IsChecked Then
tbl.ShowGridLines = True
Else
tbl.ShowGridLines = False
End If
'Add 3 columns (2 for the labels, 1 for spacing)
Dim col1 As New ColumnDefinition With {
.Width = New GridLength(labelWidthInPx, GridUnitType.Pixel)
}
Dim col2 As New ColumnDefinition With {
.Width = New GridLength(horizontalLabelSpacing, GridUnitType.Pixel)
}
Dim col3 As New ColumnDefinition With {
.Width = New GridLength(labelWidthInPx, GridUnitType.Pixel)
}
tbl.ColumnDefinitions.Add(col1)
tbl.ColumnDefinitions.Add(col2)
tbl.ColumnDefinitions.Add(col3)
'Add 5 Rows (3 for labels, 2 for spacing)
Dim row1 As New RowDefinition With {
.Height = New GridLength(labelWidthInPx, GridUnitType.Pixel)
}
Dim row2 As New RowDefinition With {
.Height = New GridLength(verticalLabelSpacing, GridUnitType.Pixel)
}
Dim row3 As New RowDefinition With {
.Height = New GridLength(labelWidthInPx, GridUnitType.Pixel)
}
Dim row4 As New RowDefinition With {
.Height = New GridLength(verticalLabelSpacing, GridUnitType.Pixel)
}
Dim row5 As New RowDefinition With {
.Height = New GridLength(labelWidthInPx, GridUnitType.Pixel)
}
tbl.RowDefinitions.Add(row1)
tbl.RowDefinitions.Add(row2)
tbl.RowDefinitions.Add(row3)
tbl.RowDefinitions.Add(row4)
tbl.RowDefinitions.Add(row5)
'Add label images
Dim reelData = CType(DataGridReels.ItemsSource, List(Of ReelInfo))
Dim rowIndex As Integer = 0
Dim colIndex As Integer = 0
For Each reel In reelData.Where(Function(r) r.IsSelected = True)
Dim partNumberData = ViewModel.DataService.GetPartNumberDataAsync(reel.PartNumber)
Dim batchData = ViewModel.DataService.GetBatchDataAsync(reel.PartNumber, reel.HENBatchNumber)
LabelImageControl.IsPrinting = True
LabelImageControl.PartNumberData = partNumberData.Result
LabelImageControl.BatchData = batchData.Result
LabelImageControl.ReelData = reel
LabelImageControl.Refresh
UpdateUI()
Dim labelImage As New Image
labelImage = GetImageFromLabel(LabelImageControl)
labelImage.Width = labelWidthInPx
labelImage.Height = labelWidthInPx
Grid.SetRow(labelImage, rowIndex)
Grid.SetColumn(labelImage, colIndex)
tbl.Children.Add(labelImage)
tbl.Refresh
colIndex += 1
If colIndex > 1 Then
colIndex = 0
rowIndex += 1
End If
Next
Dim iuc As New InlineUIContainer(tbl)
Dim p As New Paragraph(iuc)
'Create print dialog
If dlg.ShowDialog.GetValueOrDefault Then
'Create a flow document
Dim doc As New FlowDocument With {
.Name = "LabelPage",
.ColumnWidth = pageWidth,
.PagePadding = New Thickness(leftMargin, topMargin, 0, bottomMargin)
}
doc.Blocks.Add(p)
'Create IDocumentPagniatorSource from FlowDocument
Dim idpSource As IDocumentPaginatorSource = doc
Try
Me.Cursor = Cursors.Wait
dlg.PrintDocument(idpSource.DocumentPaginator, "Label Page")
Catch ex As Exception
Me.Cursor = Cursors.Arrow
MessageBox.Show("An error occurred during printing: " & ex.Message, "Print error")
Finally
Me.Cursor = Cursors.Arrow
End Try
End If
End Sub
When I send the output to the PDF printer I only get one image in the top left corner of the page/grid.
Since the user control (LabelImageControl) is in the XAML, I can see it changing while debugging. So the data is coming into the user control correctly.
When I check the grid with the XML Visualiser I see it has the same number of children as the items I selected in the datagrid.
Can anyone point me in the right direction on how to get the grid printing correctly?

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()

Allowing only the numbers in PasswordBox in WPF

I want to be enter numbers only and does not allow non-numbers, please help me with this.
this Code in TextBox But it does not work with PasswordBox
Dim textBox As TextBox = TryCast(sender, TextBox)
Dim selectionStart As Int32 = textBox.SelectionStart
Dim selectionLength As Int32 = textBox.SelectionLength
Dim newText As [String] = [String].Empty
Dim count As Integer = 0
For Each c As [Char] In textBox.Text.ToCharArray()
If [Char].IsDigit(c) OrElse [Char].IsControl(c) Then
newText += c
End If
Next
textBox.Text = newText
textBox.SelectionStart = If(selectionStart <= textBox.Text.Length, selectionStart, textBox.Text.Length)
thank you
Private Sub PbPhone_PreviewTextInput(sender As Object, e As TextCompositionEventArgs) Handles PbPhone.PreviewTextInput
Dim regex As New Regex("[0-9]+")
If Not regex.IsMatch(e.Text) Then
e.Handled = True
End If
End Sub

Any ideas how to make this FOR LOOP? VB.NET

Any Ideas on how to make this to "FOR LOOP" because the number of data that I want to show is not fixed or constant so I need to make it into for loop.
Public Sub ReportTransactionsLogs(ByVal LV As ListView)
Dim rReport As New ReportTransLog
Dim row As DataRow = Nothing
Dim ds As New DataSet
ds.Tables.Add("TransactionsLog")
With ds.Tables(0).Columns
.Add("Username")
.Add("ActionDate")
.Add("ActionTime")
.Add("Activity")
.Add("POInvoice")
End With
For Each LVI As ListViewItem In LV.Items
row = ds.Tables(0).NewRow
row(0) = LVI.Text
row(1) = LVI.SubItems(1).Text
row(2) = LVI.SubItems(2).Text
row(3) = LVI.SubItems(3).Text
row(4) = LVI.SubItems(4).Text
ds.Tables(0).Rows.Add(row)
Next
rReport.SetDataSource(ds.Tables(0))
ReportViewer.CrystalReportViewer1.ReportSource = rReport
End Sub
try like this..
For Each LVI As ListViewItem In LV.Items row = ds.Tables(0).NewRow
For i As Integer = 1 To ds.Table(0).Columns.Count()
If InlineAssignHelper(i, 0) Then
row(i) = LVI.Text
Else
row(i) =LVI.SubItems(i).Text
End If
Next
Next

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

Resources