I have a code in vb.net to select all buttons in form within flowlayoutpanel, but it returns zero.
I think problem is with flowlayoutpanel.
Dim alphabetButtons() As Button
alphabetButtons = Me.Controls.OfType(Of Button).Except(New Button() {Button1}).ToArray
Can you tell me what am I doing wrong?
I have a code in vb.net to select all buttons in form within flowlayoutpanel, but it returns zero. ... Can you tell me what am I doing wrong?
Yes. You're telling the Form to return all Controls of Type Button:
Dim alphabetButtons() As Button
alphabetButtons = Me.Controls.OfType(Of Button).Except(New Button() {Button1}).ToArray
You need to ask the FlowLayoutPanel this question.
Change Me to the name of your FlowLayoutPanel, such as FlowLayoutPanel1 in the "fixed" code below:
Dim alphabetButtons() As Button
alphabetButtons = FlowLayoutPanel1.Controls.OfType(Of Button).Except(New Button() {Button1}).ToArray
The Controls() collection only returns controls that are directly contained by that container. Each container has its own collection of child controls...
Related
Long-time WinForms programmer relatively new to WPF. I'm databinding a DataGrid in Code-Behind using a SQL Query. I reuse the DataGrid because I'm using Ribbon Tabs and reload different data in the grid dependent on the Tab selected. So binding to a static resource is not possible.
I'm trying to open a new window on a double-click event but get the following exceeption - "Unable to cast object of type 'System.Windows.RoutedEventArgs' to type 'System.Windows.Input.MouseButtonEventArgs'."
This used to be a simple thing in WinForms. My code is as follows:
Try
Dim StrRow As DataRowView = MainDataGrid.SelectedItem
Dim CellValue As String = StrRow.Row(0).ToString()
'MsgBox(CellValue)
e.Handled = True
Dim EventDetails = New EventDetails()
EventDetails.Show()
OpenEventDetailsWindow()
Catch ex As Exception
MsgBox("No Event No.for this Event")
End Try
The messagebox shows the proper string (first cell value of selected row and the new window actually pops up right before the exception is thrown. I've seen plenty of posts that say this method should work but it doesn't. I've been so far unsuccessful in fixing this. Thanks in advance.
I have subclassed the WPF DataGrid in my VB.NET application because I will need to use this component frequently but also need to have some extra features, in this case adding a new row when the tab key is pressed on the bottom right cell.
I have Overidden the OnKeyDown event of the base class. This is being triggered when the tab keys is pressed while the grid is focused, exactly as I want. However, when the event is triggered I need to be able to determine whether I'm on the bottom-right cell or not. To do this I'd like to get the SelectedItem property of my DataGrid and use that to determine which cell is selected.
I am doing all of this programmatically because I don't want users to have to write any more XAML than they would have to for a regular datagrid. It should function in exactly the same way except if you tab on the bottom right cell a new row is added and the first cell of that row is selected. this should apply no matter how many rows/columns the user has in the datagrid.
The code below shows what I want to do but the SelectedItem is not set.
Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
MyBase.OnKeyDown(e)
If e.Key = Key.Tab Then
Dim colIndex As Integer = Me.Columns.IndexOf(Me.CurrentColumn)
Dim colCount As Integer = Me.Columns.Count - 1
If -1 = colIndex Then
'the next line throws a System.NullReferenceException because SelectedItem is not set
If SelectedItem.Equals(Items(Items.Count - 1)) Then
Focus()
Dim dgrCI = New DataGridCellInfo(Items(Items.Count - 1), Columns(colIndex))
ScrollIntoView(Items(Items.Count - 1))
BeginEdit()
End If
End If
End If
End Sub
The SelectedItem property should be set to the last item in the table but is instead set to Nothing. Why is this?
Edit:
The answer from Ppp is correct. it seems that by the time the OnKeydown event is triggered the DataGrid has already lost focus. I resolved this issue by using the OnPreviewKeydown event instead.
When your tab key is pressed in the last cell you basically tab out of the datagrid which is why I am guessing your SelectedItem is null.
I am programmatically creating a GridViewColumn in WPF as follows:
Dim oGVCol As GridViewColumn = New GridViewColumn
Dim oHeaderTemplate As DataTemplate
oHeaderTemplate = New DataTemplate
Dim oGridFactory As FrameworkElementFactory = New FrameworkElementFactory(GetType(Grid))
oHeaderTemplate.VisualTree = oGridFactory
oGridFactory.SetValue(Grid.BackgroundProperty, Brushes.Transparent)
oGVCol.HeaderTemplate = oHeaderTemplate
(I have removed irrelevant code to set the content of the grid)
What I can't figure out is how to add a "click" event for the GridViewColumnHeader itself. I can add events to the Grid and any other Controls I added through the Factory objects, no problem. But I'm stuck on how to add an event to the header itself.
If you have a solution in VB.NET, great, but C# is fine too.
One (failed) attempt:
AddHandler TryCast(oGVCol.Header, GridViewColumnHeader).Click, AddressOf HeaderClick
Sadly it turns out that I cannot cast oGVCol.Header to a GridViewColumnHeader.
Ok, it may not be pretty, but I found a pretty decent solution to the problem.
Firstly, when I create the Grid Factory for the root element in the header's Visual Tree, I give it a name
oGridFactory.SetValue(Grid.NameProperty, <column name here>))
(Please note that the Names must have only letters, numbers and underscores so if your data contains column names that don't have those, you'll need to deal with that both here, to convert invalid names to valid ones, and below, to revert them back to their original names if necessary.... I won't detail that functionality here)
Also, I add an event handler to the Root "Grid" in the Template for the column header:
oGridFactory.AddHandler(Grid.SizeChangedEvent,
New SizeChangedEventHandler(AddressOf ColumnHeaderSizeChanged))
The "magic" happens in the procedure ColumnHeaderSizeChanged. This procedure is called both when the grid is Rendered the first time, but also when the user is manually resizing columns.
Signature:
Private Sub ColumnHeaderSizeChanged(sender As Object, e As SizeChangedEventArgs)
I keep a List(Of GridViewColumnHeaders) which is reset to an empty list when I need to replace the Grid with a different one. In the ColumnHeaderSizeChanged event I then do the following:
The first thing we need to do is get to the Root of the controls in the Column Header. For example, your column header may contain a TextBlock to show a column name, and icons to indicate it's been sorted up or down. That sort of thing. When the user clicks on the header they may be clicking on any of those controls, so:
Dim oParent As Object
Dim oColHeader As GridViewColumnHeader = Nothing
Dim sColHeaderName As String = String.Empty
Dim oGWH As Grid = Nothing
oParent = e.OriginalSource 'This may be any of the controls in the header.
If Not oParent Is Nothing Then
Try
While Not oParent.Parent Is Nothing
'So we keep going down the Tree until we hit the Root Parent
'which will be the main Grid created in the Grid Factory
oParent = oParent.Parent
End While
Catch
End Try
End If
'But at this point, if we still have a control, it will be the main Grid
If oParent Is Nothing Then
Exit Sub
End If
If TryCast(oParent, Grid) Is Nothing Then
'what the heck is this? This SHOULD be the Grid at the root of the Visual Tree,
'so if, for whatever reason, this is NOT a Grid, get outta here.
Exit Sub
End If
By this point we're on the main Grid, but now we need to get the GridViewColumnHeader into which this Grid has been created. So now we go to the TemplatedParent
While Not oParent.TemplatedParent Is Nothing
oParent = oParent.TemplatedParent
oColHeader = TryCast(oParent, GridViewColumnHeader)
If Not oColHeader Is Nothing Then
'This procedure is called both when the Grid View is first rendered,
'and when the user is dragging the column width.
If Mouse.LeftButton = MouseButtonState.Pressed Then
'Do something appropriate to when the user is resizing the column
Else
'Do something appropriate to when the grid
'is first Rendered or re-displayed
End If
Exit While
End If
End While
At this point we have the GridViewColumnHeader we need, so we can add it to the List and add a Handler for its Click event. moColHeaders is the List(Of GridViewColumnHeaders)
If Not oColHeader Is Nothing Then
If Not moColHeaders.Contains(oColHeader) Then
oColHeader.Name = <column name here>
moColHeaders.Add(oColHeader) 'Only need to add it once!
AddHandler oColHeader.Click, AddressOf HeaderClick
End If
End If
Now you can code your HeaderClick procedure to handle the GridViewColumnHeader.Click event.
Signature:
Private Sub HeaderClick(sender As Object, e As RoutedEventArgs)
I have dynamically created a series of grids and textblocks inside of said grids. However I am having trouble using the .FindName to call the textblock I need. My control heirarchy goes something like this:
Page -> ScrollViewer - > Grid -> Dynamically Created Grids ->
Dynamically Created Controls
This is how I am currently trying to call them and any other ways I attempted have still gotten me no where
Dim grd As Object = FindName("GridLine" + Ri.ToString())
Dim tempgrd As Grid = DirectCast(grd, Grid)
Dim txtID As Object = tempgrd.FindName("txtIDGrid" + Ri.ToString())
Dim tempID As TextBlock = DirectCast(txtID, TextBlock)
sqlID = tempID.Name
In case anyone else is searching for a similar answer I did end up solving it. You must be sure to RegisterName the controls you are creating to ensure that you can call upon it after runtime.
[disclaimer: I am new to Visual Basic.]
In a WPF, I have a TabControl containing 2 TabItems:
The first TabItem contains a bunch of URLs.
The second TabItem consists of a DockPanel that contains a cefSharp webView (chromium embedded for .net)
When I click on a url in tab1 it loads a page in the browser contained in tab2... But, it only works if I have initialized the browser first by clicking on tab2.
After doing some searching, it looks like vb.net doesn't initialize the content in a TabItem until it becomes visible. (right?)
So, my question is, how can I force a non-selected tab to initialize its content on load, in the background? (ie. so I don't have to click on the tab or switch to it first)
EDIT:
As requested, here is the relevant code:
The relevant XAML consists of a single DockPanel named "mainBox"
<DockPanel Name="mainBox" Width="Auto" Height="Auto" Background="#afe0ff" />
And here is my "code behind" vb script:
Class MainWindow : Implements ILifeSpanHandler, IRequestHandler
Shared web_view1 As CefSharp.Wpf.WebView
Shared web_view2 As CefSharp.Wpf.WebView
Public Sub init(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Loaded
'This is in a DockPanel created on the xaml named mainBox
' set up tabControl:
Dim browserTabs As New TabControl()
browserTabs.BorderThickness = Nothing
Dim tab1 As New TabItem()
tab1.Header = "My Tab"
Dim tab2 As New TabItem()
tab2.Header = "Browser"
Dim tab1Content As New DockPanel()
Dim tab2Content As New DockPanel()
tab1.Content = tab1Content
tab2.Content = tab2Content
browserTabs.Items.Add(tab1)
browserTabs.Items.Add(tab2)
mainBox.Children.Add(browserTabs)
' set up browsers:
Dim settings As New CefSharp.Settings()
settings.PackLoadingDisabled = True
If CEF.Initialize(settings) Then
web_view1 = New CefSharp.Wpf.WebView()
web_view1.Name = "myTabPage"
web_view1.Address = "http://stackoverflow.com/"
web_view2 = New CefSharp.Wpf.WebView()
web_view2.Name = "browserPage"
web_view2.Address = "https://www.google.com"
web_view2.LifeSpanHandler = Me
web_view2.RequestHandler = Me
AddHandler web_view2.PropertyChanged, AddressOf web2PropChanged
tab1Content.Children.Add(web_view1)
tab2Content.Children.Add(web_view2)
End If
End Sub
End Class
So, in its default state, tab1 is showing at start up -- the browser on tab2 (web_view2) won't initialize until I click its tab or change to its tab via script. Hope this clears it up a bit.
Your code doesn't use Windows Forms' TabPage but perhaps this might still help
As we know, Controls contained in a TabPage are not created until the
tab page is shown, and any data bindings in these controls are not
activated until the tab page is shown. This is by design and you can
call TabPage.Show() method one by one as a workaround.
via MSDN forums
Also, based on the above idea, have you tried the following.
tab2.isEnabled = True
tab1.isEnabled = True
Or:
tab2.Visibility = True
tab1.Visibility = True
Also, the BeginInit Method might help in your situation.
I had the same problem but found it initializes if I use the name of the tabpage and show (tabName1.show()) on the form load code for each page ending with the one I want displayed:
tabPage2.show()
tabPage3.show()
tabPage4.show()
tabPage5.show()
tabPage1.show()
It ripples thru and you never see the pages changing but it works. The other suggestions didn't work for me in Visual Studio 2010.