Общий метод для поиска всех элементов управления TextBox в Silverlight
У меня есть несколько элементов управления Silverlight на странице и вы хотите запросить все элементы управления типа TextBox и работать с ними.
Теперь форма Silverlight, над которой я работаю, может содержать больше элементов управления TextBox. Поэтому, когда я проверяю, имеет ли элемент управления TextBox значение, я мог бы сделать:
if (this.TextBox.Control.value.Text() != String.Empty)
{
// do whatever
}
но я бы предпочел, если бы был гибким, что я могу использовать его в ANY Silverlight, независимо от количества элементов управления TextBox, которые у меня есть.
Любые идеи о том, как я буду это делать?
Ответы
Ответ 1
Похоже, вам нужна рекурсивная подпрограмма, например 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 children
foreach (UIElement child in panel.Children)
{
GetTextBoxes(child, textBoxList);
}
}
}
}
Создайте пустой список текстовых блоков. Вызовите GetTextBoxes, передав корневой элемент управления на вашей странице (в моем случае, this.LayoutRoot) и GetTextBoxes, должны рекурсивно прокручивать каждый элемент пользовательского интерфейса, который является потомком этого элемента управления, тестируя его, будь то TextBox (добавьте его к списку), или панель, у которой могут быть потомки ее собственных, чтобы пройти через.
Надеюсь, что это поможет.:)
Ответ 2
Я уже сталкивался с этой проблемой и уведомляю ее здесь: 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>();
Ответ 3
С вашей верхней панели вы можете сделать это (моя сетка называется 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;
}
Ответ 4
Взяла начальную идею и расширила ее, чтобы она
- Использует generics, поэтому он легко справляется с несколькими типами управления.
- Поддерживает больше типов контейнеров. В моей WP7 мне нужно было поддерживать зрителей panaorama, прокрутки и т.д.... которые не являются панелями. Таким образом, это позволяет поддерживать их.
- Самая большая проблема - это сравнение строк, особенно на панели и привращенных элементах.
Код:
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;
}
}
Ответ 5
Подобная логика вышеприведенных идей также обрабатывает элементы управления с атрибутом "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;
}