I have added a usercontrol to my project like this:
Public Sub clickAutoDrillLeft(ByVal sender as Object, ByVal e as System.Windows.RoutedEventArgs)
Dim LSliderItem as New TriplexAmpsControl
me.LeftSlider.Items.Add(LSliderItem)
End sub
The "LSliderIn" object is an items control, and the "TriplexAmpsControl" is a usercontrol that has three writeonly properties declared as integers named "AmpsPhaseA", "AmpsPhaseB", and "AmpsPhaseC".
If I instantiate the control at runtime as above, I can immediately assign a value to one of the properties like:
Public Sub clickAutoDrillLeft(ByVal sender as Object, ByVal e as System.Windows.RoutedEventArgs)
Dim LSliderItem as New TriplexAmpsControl
me.LeftSlider.Items.Add(LSliderItem)
LSliderItem.AmpsPhaseA = 50
End sub
But only within the sub routine. I don't know how to reference the control values elsewhere in the form, because if I try to call the control by its name from some other sub, the compiler tells me, naturally, that the control is not part of the project because it has not been created yet.
All I have been able to find on the subject concerns the creation of controls in code-behind, but noting on how to connect to user controls instantiated the way I have done it.
(Pre-emptive note: excuse my VB - i'm a C# coder :)
You need to create a module level variable:
Dim _lSliderItem as TriplexAmpsControl
then in your code somewhere:
Public Sub clickAutoDrillLeft(ByVal sender as Object, ByVal e as System.Windows.RoutedEventArgs)
_lSliderItem = New TriplexAmpsControl
me.LeftSlider.Items.Add(_lSliderItem)
End sub
Or if that approach is out of the question for some reason then you can give the dynamically created control a name and later in your code use the FrameworkElement.FindName() method (most UI controls will be derived from FrameworkElement). Or you can code up your own little search function like this (excuse the C# syntax, it shouldn't be a problem for you to translate it to VB):
public static DependencyObject FindChild(this DependencyObject o, Type childType, string childName, bool checkObjectItself)
{
if (checkObjectItself && (((string)o.GetValue(FrameworkElement.NameProperty)) == childName))
return o;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++)
{
DependencyObject obj2 = VisualTreeHelper.GetChild(o, i).FindChild(childType, childName, true);
if (obj2 != null)
return obj2;
}
return null;
}
Related
I am new to coding with visual basic.
Recently, I was tasked by my professor to write a programme that allows the user to enter five words. The words then should be sorted and displayed in alphabetical order.
To do this I decided the best approach would be to use an array.
My thinking was that if I created a counter at the start, I can create a different value for each column of the array when a button is clicked.
If the array exceeds five I have a message box pop-up that resets the code (although I realise I will also have to clear the contents of the array).
My problem arises in displaying the array. I have looked for solutions online, and none have helped me as of yet.
I need to sort the array into alphabetical order and then display it in a label box (lbl_DisplayArray). As I do not know the values of the array, this has proved tricky.
My code is below:
Public Class Form1
Dim i As Integer = 0
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim Array(4) As String
Array(i) = txt_UserWords.Text
End Sub
Private Sub btn_Next_Click(sender As Object, e As EventArgs) Handles btn_Next.Click
i += 1
If i >= 5 Then
i = 0
MsgBox("Array Limit Exceeded. Code Reset")
txt_UserWords.Text = ""
End If
End Sub
Private Sub btn_Sort_Click(sender As Object, e As EventArgs) Handles btn_Sort.Click
lbl_DisplayArray.Text =
End Sub
End Class
You'd be better off using
private myList as new List(of String).
Then to sort them you just call the .Sort() method. Just call .Add(txt_userWords.Text) to add the new string and use .Count to see how many of them you have.
When you're adding them to the label you can use
lbl_DisplayArray.Text = String.Join(vbCrLf, myList)
You'll need the list of to be a member of the class instead of a local variable (as you have declared Array). This will keep it alive and allow you to access it in other methods.
---------- edit ----------
Public Class Form1
private myList as new List(of String)
Private Sub btn_Next_Click(sender As Object, e As EventArgs) Handles btn_Next.Click
If myList.Count >= 5 Then
myList.Clear
Else
myList.add(txt_UserWords.Text)
End If
txt_UserWords.Text = ""
End Sub
Private Sub btn_Sort_Click(sender As Object, e As EventArgs) Handles btn_Sort.Click
myList.Sort()
lbl_DisplayArray.Text = String.Join(vbcrlf, myList)
End Sub
End Class
Does anyone know how to dynamically add an array to a bunch of comboboxes in VB.net? I could really use the help (I've been struggling with this all day). When I try to do it my way I get an error on form load.
My code:
Private Sub Form1_Load(ByVal sender as Object, ByVal e as EventArgs) Handles Me.Load
Dim MyArray() as String = {"a","b","c"}
For each ctl as ComboBox in Me.Controls
if ctl.tag = "yadda" then ctl.Items.AddRange(MyArray)
Next
End Sub
Error: "Unable to cast object of type '...Button' to type '...Combobox'."
I've tried so many variations to this code but I just can't get it to work. I will eventually have nearly a hundred similarly constructed comboboxes in my application, and I'd like to be able to programmatically initialize their items. Could someone please help?
Thanks,
Elias
This is the way to do it :
Public Class Form1
Function getControl(ByVal controlName As String) As Control
Dim numCtrls = Me.Controls.Count()
For I As Integer = 0 To numCtrls - 1
If Me.Controls.Item(I).Name = controlName Then
If TypeOf Me.Controls.Item(I) Is ComboBox Then
Return CType(Me.Controls(controlName), ComboBox)
End If
End If
Next
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim myArray As Array = {"a", "b", "c"}
Dim myComboBox As ComboBox
For Each ctl As Control In Me.Controls
If TypeOf ctl Is ComboBox Then
If ctl.Tag = "yadda" Then
myComboBox = getControl(ctl.Name)
myComboBox.Items.AddRange(myArray)
End If
End If
Next
End Sub
End Class
You loop through all controls (buttons, combo, etc ...) then you check if it is the type you want (ComboBox) and do whatever you need.
Good luck !
I have a WPF application I am working on that uses the Entity Framework 4.0 an Observable Collection and a few CollectionViewSources. On my form i have two text boxes i use to filter my data and then display it into a listbox based on what I have filtered it by. What I need to do is to have the user select an item from the listbox and hit a button ("Select") and the information is displayed wiht appropriate collections in a whole new window.
So far I have:
Imports System.Data.Objects
Public Class SearchText
Private db As New CraftingProjectsEntities
Private ProjectsData As ProjectsCollection
Private ProjectViewSource As CollectionViewSource
Private MaterialsViewSource As CollectionViewSource
Private ColoringsViewSource As CollectionViewSource
Private DirectionsViewSource As CollectionViewSource
Private SpecialsViewSource As CollectionViewSource
Private WithEvents ProjectView As ListCollectionView
Private MaterialsView As BindingListCollectionView
Private ColoringsView As BindingListCollectionView
Private SpecialsView As BindingListCollectionView
Private DirectionsView As BindingListCollectionView
Private Sub SearchText_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
Dim query = From r In db.Projects
Where r.Materials.Count > 1
Select r
Me.ProjectViewSource = CType(Me.FindResource("ProjectsViewSource"), CollectionViewSource)
Me.DirectionsViewSource = CType(Me.FindResource("DirectionsViewSource"), CollectionViewSource)
Me.ColoringsViewSource = CType(Me.FindResource("ColoringsViewSource"), CollectionViewSource)
Me.SpecialsViewSource = CType(Me.FindResource("SpecialsViewSource"), CollectionViewSource)
Me.MaterialsViewSource = CType(Me.FindResource("MaterialsViewSource"), CollectionViewSource)
Me.ProjectViewSource.Source = Me.ProjectsData
Me.ProjectView = CType(Me.ProjectViewSource.View, ListCollectionView)
Me.DirectionsView = CType(Me.DirectionsViewSource.View, BindingListCollectionView)
Me.ColoringsView = CType(Me.ColoringsViewSource.View, BindingListCollectionView)
Me.MaterialsView = CType(Me.MaterialsViewSource.View, BindingListCollectionView)
Me.SpecialsView = CType(Me.SpecialsViewSource.View, BindingListCollectionView)
MyLists.ItemsSource = ProjectsData
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
Dim query2 As ObjectQuery(Of Project) = Nothing
Dim query = From p In db.Projects
Select p
If TextBox2.Text.Length > 1 And TextBox1.Text.Length > 1 Then
query2 = query.Where(Function(p) p.Materials.Any(Function(m) m.Material1.ToLower().Contains(Me.TextBox1.Text)) And
p.Materials.Any(Function(m) m.Material1.ToLower().Contains(Me.TextBox2.Text)))
ElseIf TextBox2.Text.Length < 1 And TextBox1.Text.Length > 1 Then
query2 = query.Where(Function(p) p.Materials.Any(Function(m) m.Material1.ToLower().Contains(Me.TextBox1.Text)))
Else
MessageBox.Show("What are you looking for?")
Return
End If
Me.ProjectsData = New ProjectsCollection(query2.ToList(), db)
MyLists.ItemsSource = ProjectsData
End Sub
**Works great through here... Below is where i get lost trying to get the selected item to the new window**
Private Sub btnSelect_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnSelect.Click
Dim mychoice As New MyChoice
Dim selitem = Me.MyLists.SelectedItem
mychoice.ProjectsData = (selitem)
mychoice.Show()
Me.Close()
End Sub
End Class
Any thoughts on how I could do this or where I could find an example showing the proper way of doing this would be extremely appreciated. Thanks.
Adam
Sorry.... not using MVVM if this helps.
Make your model Project a parameter of the MyChoice window class. Depending on whether it's required for the window, make Project a required or optional parameter of the MyChoice constructor. Set it as the Data Context for your new window's Layout Root, set it as a property of the Window class itself, or put it in the View Model; whichever is appropriate.
I want to be able to accept a NULL date using the DateTimePicker control.
The "Checked" property appears to be intended to specify whether the control "holds a date" or now. However, when "unchecked", the date still appears, though it appears disabled. To me, this is distracting. If the intent of the unchecked checkbox is to indicate that there is no date value, why is there ANY date value disable or otherwise that appears in the textbox? It seems to me that if the control is unchecked, the textbox should be EMPTY and that seeing a dimmed date value when the user really wants "no value" is distracting.
If the user toggled the checkbox on, then I would like the ability to place a default value into the textbox.
I am considering creating a usercontrol that toggles between a dateTimePicker control and a textBox, but I hate to go through this trouble.
I tried looking a Telerik's DateTimePicker but trying to get decent null handling functionality out of that control seems worse. I'd love to see a working example of what one of you think is a user-friendly code example with either the std MS or Telerik DateTimePicker control that accepts null input.
I've looked at a few opensource controls, but every time they fix one issue, they introduce others.
EDIT:
See my answer below. It seems to work fine, now I just want to make it part of every DateTimePicker's behavior.
I had the same problem. Well, actually I'm smart enough to understand, but my users had a problem.
I solved by removing the checkbox, and adding 2 radio buttons. Looks something like this now:
(using pseudo UI)
O No value entered
O | 1/1/2010 |V|
The top radiobutton is checked when there is no value (null), the bottom one when there is a value. I do not hide, or disable the bottom control, and users seem to understand.
The downside is, that it takes a lot more space.
PS: Next thing users will complain about is using the scroll-wheel when a combo-box has focus.
Klugey, but it seems to get the job done. If the checkbox is not checked, assume a NULL value.
Private Sub DateTimePicker1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DateTimePicker1.ValueChanged
If DateTimePicker1.Checked Then
DateTimePicker1.Format = DateTimePickerFormat.Short 'Or whatever the original format was
Else
DateTimePicker1.Format = DateTimePickerFormat.Custom
DateTimePicker1.CustomFormat = " "
End If
End Sub
OK, the next question...How do I roll this behavior into a subclassed DateTimePicker? What I want to do is to capture the original values of the Format and CustomFormat properties as set in the Properties window. But, this clearly isn't the way to do it.
Here's my feeble attempt:
Public Class NullableDateTimePicker
Inherits DateTimePicker
Private _OriginalFormat As DateTimePickerFormat
Private _OriginalCustomerFormat As String
Private Sub NullableDateTimePicker_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ValueChanged
If Me.Checked Then
Me.Format = _OriginalFormat
Me.CustomFormat = _OriginalCustomerFormat
Else
Me.Format = DateTimePickerFormat.Custom
Me.CustomFormat = " "
End If
End Sub
Private Sub _DP_FormatChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Static Count As Integer
If Count = 0 Then
_OriginalFormat = Me.Format
_OriginalCustomerFormat = Me.CustomFormat
End If
Count += 1
End Sub
Public Sub New()
AddHandler MyBase.FormatChanged, AddressOf _DP_FormatChanged
End Sub
End Class
I realise this is many years after your initial question but here's a subclass of the Telerik RadDateTimePicker that does what you were asking for:
Imports Telerik.WinControls.UI
Public Class DateTimePickerWithNull
Inherits Telerik.WinControls.UI.RadDateTimePicker
Private ReadOnly _calendar As RadCalendar
Sub New()
Dim calendarBehavior As RadDateTimePickerCalendar = Me.DateTimePickerElement.GetCurrentBehavior()
calendarBehavior.DropDownMinSize = New Size(220, 150)
_calendar = calendarBehavior.Calendar
_calendar.ShowFooter = True
AddHandler _calendar.ClearButton.Click, AddressOf ClearButton_Click
AddHandler _calendar.TodayButton.Click, AddressOf TodayButton_Click
End Sub
Private Sub ClearButton_Click(sender As Object, e As EventArgs)
'Do this to put the calendar away
_calendar.SelectedDate = _calendar.FocusedDate
'Then clear
Me.SetToNullValue()
End Sub
Private Sub TodayButton_Click(sender As Object, e As EventArgs)
_calendar.SelectedDate = _calendar.FocusedDate
End Sub
End Class
To get the value of the picker:
If DateTimePicker1.Value.Date = DateTimePicker1.NullDate Then
Label1.Text = "Null"
Else
Label1.Text = DateTimePicker1.Value.ToLongDateString
End If
A bit tricky to get right. This looked good:
Imports System.ComponentModel
Public Class MyDateTimePicker
Inherits DateTimePicker
Implements ISupportInitialize
Public Sub New()
Me.ShowCheckBox = True
Me.NullDate = True
End Sub
Private CustomFormatBacking As String = ""
Private FormatBacking As DateTimePickerFormat = DateTimePickerFormat.Long
<DefaultValue(True)> _
<Bindable(True)> _
Public Property NullDate() As Boolean
Get
Return Not Me.Checked
End Get
Set(ByVal value As Boolean)
Me.Checked = Not value
End Set
End Property
<DefaultValue("")> _
<Localizable(True)> _
<RefreshProperties(RefreshProperties.Repaint)> _
Public Shadows Property CustomFormat() As String
Get
Return CustomFormatBacking
End Get
Set(ByVal value As String)
CustomFormatBacking = value
If DesignMode Or Not NullDate Then MyBase.CustomFormat = value
End Set
End Property
<RefreshProperties(RefreshProperties.Repaint)> _
Public Shadows Property Format() As DateTimePickerFormat
Get
Return FormatBacking
End Get
Set(ByVal value As DateTimePickerFormat)
FormatBacking = value
If DesignMode Or Not NullDate Then MyBase.Format = value
End Set
End Property
<DefaultValue(true)> _
<Bindable(True)> _
<DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Shadows Property Checked() As Boolean
Get
Return MyBase.Checked
End Get
Set(ByVal value As Boolean)
MyBase.Checked = value
End Set
End Property
Private Sub updateNullState()
If NullDate and Not DesignMode Then
MyBase.CustomFormat = " "
MyBase.Format = DateTimePickerFormat.Custom
Else
MyBase.CustomFormat = CustomFormatBacking
MyBase.Format = FormatBacking
End If
End Sub
Public Sub BeginInit() Implements System.ComponentModel.ISupportInitialize.BeginInit
End Sub
Public Sub EndInit() Implements System.ComponentModel.ISupportInitialize.EndInit
updateNullState()
End Sub
Protected Overrides Sub OnValueChanged(ByVal eventargs As System.EventArgs)
MyBase.OnValueChanged(eventargs)
updateNullState()
End Sub
End Class
I've a created a simple scrollviewer (pnlDayScroller) and want to have a separate horizontal scrollbar (associated scroller) to do the horizontal scrolling. All works with the below code accept I need to bind the visibility of the associated scroller.
I can't simply bind this to the visibility property of the horizontal template part of the scroll viewer as I've set this to be always hidden. The only way I can think to do this is to bind the visibility of the associated scroller to a function such that
If associatedScroller.scrollableWidth > 0 then
associatedScroller.visibility = visibility.visible
else
associatedScroller.visibility = visibility.collapsed
end if
Is this possible to do and if so how do I do it?
Private Sub pnlDayScroller_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles pnlDayScroller.Loaded
Dim binViewport, binMax, binMin, binSChange, binLChange As Binding
Dim horizontalScrollBar As Primitives.ScrollBar = CType(pnlDayScroller.Template.FindName("PART_HorizontalScrollBar", pnlDayScroller), Primitives.ScrollBar)
binViewport = New Binding("ViewportSize")
binViewport.Mode = BindingMode.OneWay
binViewport.Source = horizontalScrollBar
associatedScroller.SetBinding(Primitives.ScrollBar.ViewportSizeProperty, binViewport)
binMax = New Binding("Maximum")
binMax.Mode = BindingMode.OneWay
binMax.Source = horizontalScrollBar
associatedScroller.SetBinding(Primitives.ScrollBar.MaximumProperty, binMax)
binMin = New Binding("Minimum")
binMin.Mode = BindingMode.OneWay
binMin.Source = horizontalScrollBar
associatedScroller.SetBinding(Primitives.ScrollBar.MinimumProperty, binMin)
binSChange = New Binding("SmallChange")
binSChange.Mode = BindingMode.OneWay
binSChange.Source = horizontalScrollBar
associatedScroller.SetBinding(Primitives.ScrollBar.SmallChangeProperty, binSChange)
binLChange = New Binding("LargeChange")
binLChange.Mode = BindingMode.OneWay
binLChange.Source = horizontalScrollBar
associatedScroller.SetBinding(Primitives.ScrollBar.LargeChangeProperty, binLChange)
End Sub
Private Sub associatedScroller_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.RoutedPropertyChangedEventArgs(Of Double)) Handles associatedScroller.ValueChanged
pnlDayScroller.ScrollToHorizontalOffset(e.NewValue)
end sub
FOLLOW UP (thanks to JustABill) :
I've add this code into the pnlDayScroller sub above (I've discovered scrollableWidth is a property of scrollviewer not scrollbar, but the maximum property gives a result I can use instead)
binVisibility = New Binding("Maximum")
binVisibility.Mode = BindingMode.OneWay
binVisibility.Source = horizontalScrollBar
binVisibility.Converter = New ScrollableConverter
associatedScroller.SetBinding(Primitives.ScrollBar.VisibilityProperty, binVisibility)
and I've created this class
Public Class ScrollableConverter
Implements IValueConverter
Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object,
ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert
Dim dblMaximum As Double
If targetType IsNot GetType(Visibility) Then
Throw New InvalidOperationException("The target must be a visibility")
Else
dblMaximum = CType(value, Double)
Debug.WriteLine("Value of double is " & dblMaximum)
If dblMaximum > 0 Then
Return Visibility.Visible
Else
Return Visibility.Collapsed
End If
End If
End Function
Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object,
ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
Throw New NotSupportedException()
End Function
End Class
And the problem is resolved.
You need a ValueConverter. Bind to the scrollableWidth property, and add your ValueConverter to the binding's Converter property. That example's in C#, but the concept's pretty simple, and I'm sure there's VB.Net examples around if you look.
The short form of what you need to do is:
Create a new class that implements IValueConverter (I think it's in System.ComponentModel).
Fill in the Convert method with your first code block, except use the "value" parameter instead of scrollableWidth and return the visibility.
Add an appropriate xmlns for your local classes.
Add a StaticResource of your new ValueConverter to your Window/UserControl/whatever.
Bind the Visibility property to the scrollableWidth property using this ValueConverter.