Общий метод, чтобы найти все элементы управления TextBox в Silverlight - PullRequest
11 голосов
/ 03 марта 2009

У меня есть несколько элементов управления Silverlight на странице, и я хочу запросить все элементы управления, имеющие тип TextBox и работающие.

Теперь форма Silverlight, над которой я работаю , может иметь больше элементов управления TextBox. Поэтому, когда я проверяю, имеет ли элемент управления TextBox значение, я мог бы сделать:

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

но я бы предпочел, если бы проявил гибкость, использовать это в ЛЮБОЙ форме Silverlight независимо от количества элементов управления TextBox, которые у меня есть.

Есть идеи, как мне поступить?

Ответы [ 5 ]

14 голосов
/ 03 марта 2009

Я уже сталкивался с этой проблемой и уведомляю ее здесь: http://megasnippets.com/en/source-codes/silverlight/Get_all_child_controls_recursively_in_Silverlight

Здесь у вас есть универсальный метод для рекурсивного поиска в VisualTree всех текстовых полей:

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

    return children;
}

Используйте этот метод, чтобы найти все текстовые поля:

var textBoxes = GetChildrenRecursively(LayoutRoot).OfType<TextBox>();
10 голосов
/ 03 марта 2009

Звучит так, как будто вам нужна рекурсивная процедура, такая как GetTextBoxes ниже:

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);
            }
        }
    }
}

Создание пустого списка TextBoxes. Вызовите GetTextBoxes, передав корневой элемент управления на вашей странице (в моем случае это this.LayoutRoot), и GetTextBoxes должен рекурсивно перебирать каждый элемент пользовательского интерфейса, являющийся потомком этого элемента управления, проверяя, является ли он TextBox (добавьте его в список) или панель, в которой могут быть свои потомки.

Надеюсь, это поможет. :)

3 голосов
/ 12 августа 2011

Взял Скотта начальную идею и расширил ее так, чтобы она

  1. Использует дженерики, поэтому легко справляется с несколькими типами элементов управления.
  2. Поддерживает больше типов контейнеров. В моем WP7 мне нужно было поддерживать панорамы, прокрутки и т. Д., Которые не являются панелями. Так что это позволяет поддерживать их.
  3. Самая большая проблема - это сравнение строк, особенно на панели и полученных элементах.

Код:

private static void GetControls<T>(UIElement uiElement, List<T> controlList) where T : UIElement
{
    var frameworkFullName = uiElement.GetType().FullName;
    if (frameworkFullName == typeof(T).FullName)
    {
        controlList.Add(uiElement as T);
        return;
    }

    if (frameworkFullName == typeof(Panel).FullName ||
        frameworkFullName == typeof(Grid).FullName ||
        frameworkFullName == typeof(StackPanel).FullName)
    {
        foreach (var child in (uiElement as Panel).Children)
        {
            GetControls(child, controlList);
        }
        return;
    }

    if (frameworkFullName == typeof(Panorama).FullName)
    {
        foreach (PanoramaItem child in (uiElement as Panorama).Items)
        {
            var contentElement = child.Content as FrameworkElement;
            if (contentElement != null)
            {
                GetControls(contentElement, controlList);
            }
        }
        return;
    }

    if (frameworkFullName == typeof(ScrollViewer).FullName)
    {
        var contentElement = (uiElement as ScrollViewer).Content as FrameworkElement;
        if (contentElement != null)
        {
            GetControls(contentElement, controlList);
        }
        return;
    }
}
3 голосов
/ 03 марта 2009

Вы можете сделать это с самой верхней панели (моя сетка называется ContentGrid)

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

Однако при этом будут найдены только те текстовые поля, которые являются непосредственными дочерними элементами. Может помочь какая-то рекурсия, подобная приведенной ниже, но я думаю, что должен быть лучший способ.

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;
}
1 голос
/ 09 мая 2013

Подобно логике, приведенной выше, для обработки элементов управления с атрибутом «Content», таким как TabItems и Scrollviewers, где дочерние элементы могут быть встроены на более низком уровне Находит всех детей:

   IEnumerable<DependencyObject> GetControlsRecursive(DependencyObject root)
   {
       List<DependencyObject> elts = new List<DependencyObject>();
       elts.Add(root);
       string type = root.GetType().ToString().Replace("System.Windows.Controls.", "");
       switch (root.GetType().ToString().Replace("System.Windows.Controls.", ""))
       {
           case "TabItem":
               var TabItem = (TabItem)root;
               elts.AddRange(GetControlsRecursive((DependencyObject)TabItem.Content));
               break;
           case "ScrollViewer":
               var Scroll = (ScrollViewer)root;
               elts.AddRange(GetControlsRecursive((DependencyObject) Scroll.Content));
               break;
           default: //controls that have visual children go here
               for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++) elts.AddRange(GetControlsRecursive(VisualTreeHelper.GetChild(root, i)));
               break;
       }
       return elts;
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...