Is there a way to iterate in a ListBox Items templates?
-
22-08-2019 - |
Question
I have a list box that contains items that are represented by a single textbox.
When the user clicks a button, I want to iterate thru all these text boxes and check if their binding expressions are clean of errors; Should be something like:
Dim errCount = 0
For Each item In MyListBox.ListBoxItems 'There is no such thing ListBoxItems which is actually what I am looking for.
Dim tb As TextBox = item '.........Dig in item to extract the textbox from the visual tree.
errCount += tb.GetBindingExpression(TextBox.TextProperty).HasError
Next
If errCount Then
'Errors found!
End If
Any discussion would be really appreciated. Thanks.
Solution
There may be an easier way to do this, but here is one option that will work:
1) Iterate through the list of items.
Because you are using items source, ListBox.Items
will refer to the data items in the ItemsSource.
for (int i = 0; i < ListBox.Items.Count; i++)
{
// do work as follows below...
}
2) Get the containers for these items.
DependencyObject obj = ListBox.ItemContainerGenerator.ContainerFromIndex(i);
3) Use VisualTreeHelper to search for a TextBox child of the container visual.
TextBox box = FindVisualChild<TextBox>(obj);
Use this function to search for a visual child of the correct type:
public static childItem FindVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
// Search immediate children
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child is childItem)
return (childItem)child;
else
{
childItem childOfChild = FindVisualChild<childItem>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
4) Finally, examine the binding on the TextBox.
All put together, something like this:
private bool ValidateList(ListBox lb)
{
for (int i = 0; i < lb.Items.Count; i++)
{
DependencyObject obj = lb.ItemContainerGenerator.ContainerFromIndex(i);
TextBox box = FindVisualChild<TextBox>(obj);
if (!TestBinding(box))
return false;
}
return true;
}
OTHER TIPS
Translation of previous post to VB:
1)
For i As Integer = 0 To ListBox.Items.Count - 1
' do work as follows below...
Next
2)
Dim obj As DependencyObject = ListBox.ItemContainerGenerator.ContainerFromIndex(i)
3)
Dim box As TextBox = FindVisualChild(Of TextBox)(obj)
'************************
Public Shared Function FindVisualChild(Of ChildItem As DependencyObject)(ByVal obj As DependencyObject) As ChildItem
' Search immediate children
For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(obj) - 1
Dim child As DependencyObject = VisualTreeHelper.GetChild(obj, i)
If TypeOf child Is ChildItem Then
Return child
Else
Dim childOfChild As ChildItem = FindVisualChild(Of ChildItem)(child)
If childOfChild IsNot Nothing Then Return childOfChild
End If
Next
Return Nothing
End Function
4)
Private Function ValidateList(ByVal lb As ListBox) As Boolean
For i As Integer = 0 To lb.Items.Count - 1
Dim obj As DependencyObject = lb.ItemContainerGenerator.ContainerFromIndex(i)
Dim box As TextBox = FindVisualChild(Of TextBox)(obj)
If Not TestBinding(box) Then
Return False
End If
Next
Return True
End Function