tags:

views:

4445

answers:

3

Good Day,

I have several Silverlight controls on a page and want query all the controls that are of type TextBox and have that working.

Now the Silverlight form I'm working on could have more TextBox controls added. So when I test to see if a TextBox control has a value, I could do:

if (this.TextBox.Control.value.Text() != String.Empty)
{
    // do whatever
}

but I'd rather have if flexible that I can use this on ANY Silverlight form regardless of the number of TextBox controls I have.

Any ideas on how I would go about doing that?

Thanks in Advance

A: 

From your top most panel you can do this (my grid is called ContentGrid)

var textBoxes = this.ContentGrid.Children.OfType<TextBox>();
var nonEmptyTextboxes = textBoxes.Where(t => !String.IsNullOrEmpty(t.Text));
foreach (var textBox in nonEmptyTextboxes)
{
    //Do Something
}

However this will only find the textboxes that are immediate children. Some sort of recursion like below would help, but I'm thinking there must be a better way.

private List<TextBox> SearchForTextBoxes(Panel panel)
{
    List<TextBox> list = new List<TextBox>();
    list.AddRange(panel.Children.OfType<TextBox>()
        .Where(t => !String.IsNullOrEmpty(t.Text)));

    var panels = panel.Children.OfType<Panel>();
    foreach (var childPanel in panels)
    {
        list.AddRange(SearchForTextBoxes(childPanel));
    }
    return list;
}
Ray
This is definitely a step in the right direction. Is there some sort of way to use Reflection to get information about a control if it's a certain control type?
coson
What do you mean? The .OfType extension method will only return controls of the type specified. And they'll be typed correctly. What sort of information are you after?
Ray
+2  A: 

It sounds like you need a recursive routine like GetTextBoxes below:

void Page_Loaded(object sender, RoutedEventArgs e)
{
    // Instantiate a list of TextBoxes
    List<TextBox> textBoxList = new List<TextBox>();

    // Call GetTextBoxes function, passing in the root element,
    // and the empty list of textboxes (LayoutRoot in this example)
    GetTextBoxes(this.LayoutRoot, textBoxList);

    // Now textBoxList contains a list of all the text boxes on your page.
    // Find all the non empty textboxes, and put them into a list.
    var nonEmptyTextBoxList = textBoxList.Where(txt => txt.Text != string.Empty).ToList();

    // Do something with each non empty textbox.
    nonEmptyTextBoxList.ForEach(txt => Debug.WriteLine(txt.Text));
}

private void GetTextBoxes(UIElement uiElement, List<TextBox> textBoxList)
{
    TextBox textBox = uiElement as TextBox;
    if (textBox != null)
    {
     // If the UIElement is a Textbox, add it to the list.
     textBoxList.Add(textBox);
    }
    else
    {
     Panel panel = uiElement as Panel;
     if (panel != null)
     {
      // If the UIElement is a panel, then loop through it's children
      foreach (UIElement child in panel.Children)
      {
       GetTextBoxes(child, textBoxList);
      }
     }
    }
}

Instantiate an empty list of TextBoxes. Call GetTextBoxes, passing in the root control on your page (in my case, that's this.LayoutRoot), and GetTextBoxes should recursively loop through every UI element that is a descendant of that control, testing to see if it's either a TextBox (add it to the list), or a panel, that might have descendants of it's own to recurse through.

Hope that helps. :)

Scott Ferguson
Many Thanks!This is definitely what I was looking for. Now I just need to see if I can the the UIElement class to extract more information. (i.e. Control x:Name if possible)
coson
Oh please. I had that an hour before he did.
Ray
+3  A: 

I have already faced this issue and notify it here : Get all child controls recursively

Here you have a generic method to find recursively in the VisualTree all TextBoxes:

IEnumerable<DependencyObject> GetChildsRecursive(DependencyObject root)
{
    List<DependencyObject> elts = new List<DependencyObject>();
    elts.Add(root);
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
        elts.AddRange(GetChildsRecursive(VisualTreeHelper.GetChild(root, i)));

    return elts;
}

Use this method like this to find all TextBoxes:

var textBoxes = GetChildsRecursive(LayoutRoot).OfType<TextBox>();
tucod
Same Code as VB.Net:Public Shared Function GetChildsRecursive(ByVal Root As DependencyObject) As IEnumerable(Of DependencyObject) Dim Found As New List(Of DependencyObject) Found.Add(Root) For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(Root) - 1 Found.AddRange(GetChildsRecursive(VisualTreeHelper.GetChild(Root, i))) Next Return Found End Function
Christoph