Percorrer TextBox de uma ChildWindow
-
quinta-feira, 28 de julho de 2011 12:56
Bom Dia, Pessoal.
Como posso percorrer todos os TextBox de uma ChildWindow silverlight, para modificar o TextChanged ?
Att.
Respostas
-
sexta-feira, 29 de julho de 2011 13:35Moderador
Manoel,
As opções dadas pelo Américo e pelo E. Pacheco são simples e válidas, mas há uma forma um pouco mais genérica de fazer esse tipo de busca nos objetos da tela, usando uma classe chamada VisualTreeHelper. Essa classe permite que você faça buscas na árvore visual da aplicação, tanto pra cima quanto para baixo.
Eu criei a função abaixo para facilitar ainda mais o uso dessa classe.
public static T[] SearchUIElements<T>(UIElement root, int maxlevel = int.MaxValue, int level = 0) where T : UIElement { var result = new List<T>(); if (root != null) { if (root is T) { result.Add(root as T); } if (level < maxlevel) { var childrencount = VisualTreeHelper.GetChildrenCount(root); DependencyObject child; for (var i = 0; i < childrencount; i++) { child = VisualTreeHelper.GetChild(root, i); if (child is UIElement) { result.AddRange(SearchUIElements<T>(child as UIElement, maxlevel, level + 1)); } } } } return result.ToArray(); }
Suponhamos que você tenha o seguinte XAML:
<Grid x:Name="LayoutRoot" Background="White"> <TextBox /> <TextBox /> <Grid> <TextBox /> <TextBox /> <Grid> <TextBox /> </Grid> </Grid> </Grid>
Podemos usar a função das seguintes formas:
TextBox[] textboxes = SearchUIElements<TextBox>(LayoutRoot); //acha TODOS os 5 campos TextBox textboxes = SearchUIElements<TextBox>(LayoutRoot, 1); //acha apenas os 2 campos TextBox de LayoutRoot textboxes = SearchUIElements<TextBox>(LayoutRoot, 2); //acha 4. Os 2 acima e os 2 que estão no primeiro Grid filho TextBlock[] textblocks = SearchUIElements<TextBlock>(LayoutRoot); //não acha nada, mas procura por TODOS campos TextBlock
Essa é uma função genérica, capaz de achar qualquer tipo de controle na tela. Essa função é executada de forma recursiva até que não existam mais filhos na arvore visual ou até atingir o nível hierárquico máximo passado no segundo parâmetro (que é opcional). O resultado dessa função será um array do tipo de controle solicitado. Sempre será retornado um array, mesmo que seja vazio.
Mas eu fiquei com uma dúvida: Para que você precisa achar todos os campos TextBox dessa ChildWindow? Qual é exatamente a sua necessidade? Estou perguntando isso pois se você estiver fazendo essa varredura para ler os valores dos campos, a melhor forma seria usar Binding e não manipular a tela. Quanto menos o seu código souber sobre a estrutura da tela, mais fácil será de dar manutenção na aplicação no futuro. Sim, há várias situações onde realmente é necessário fazer algum tipo de varredura na tela ou manipular os controles diretamente, mas quanto menos fizermos isso, melhor.
Se voce quiser elaborar mais sobre o assunto, estou a disposição para ajudar a encontrar a melhor solução para o seu problema.
Atenciosamente,
Kelps Leite de Sousa | MVP Silverlight
blog: http://kelps.net
twitter : http://twitter.com/kelps
Não se esqueça de "marcar como resposta" o ítem que lhe ajudou.
- Sugerido como Resposta E. Pacheco sexta-feira, 29 de julho de 2011 13:40
- Editado Kelps Leite de SousaMVP, Moderator sexta-feira, 29 de julho de 2011 16:00 melhoria na função (verificação de nulo)
- Marcado como Resposta Manoel Bruno P. Lima segunda-feira, 29 de agosto de 2011 19:28
Todas as Respostas
-
quinta-feira, 28 de julho de 2011 13:06
Cara, pegar o "LayoutRoot" da sua ChildWindow e percorre (com um foreach, por exemplo), os itens da propriedade Children dele.
Ai uso o "is" pra saber se é TextBox, ou se é um item que contem itens, e se for o caso, faz o mesmo com esse itens ;}
Quando vc achar seus TextBox é só vc fazer a atribuição normal de métodos a eventos.
-
quinta-feira, 28 de julho de 2011 13:58
Olá,
A resposta do E.Pacheco está correta , só para contextualizar :
foreach (UIElement child in LayoutRoot.Children) { if (child is TextBox) { TextBox t = child as TextBox; t.TextChanged +=new TextChangedEventHandler(t_TextChanged); } }
Espero ter ajudado.
Américo Arvani
MCP Frw web 2.0 / MCPD Frw web/win/wcf 3.5
Se ajudou , marque como resposta.
http://americoarvani.blogspot.com
-
quinta-feira, 28 de julho de 2011 14:06
Américo, seu código só tem uma falha: ao percorrer o LayoutRoot você pode se deparar com outro Panel (UIElement com Childrens), que pode conter outro Panel e assim por diante, e no final de tudo, pode haver um TextBox (ou não).
Ia deixar ele montar o código sozinho, mas vou postá-lo então:
public void ApplyChangeToAll(Panel e) { foreach (var item in e.Children) if (item is TextBox) Size(item as ComboBox); else if (item is Panel) SizeAll(item as Panel); } public void ApplyChange(TextBox e) { //Faça aqui as mudanças no TextBox (e); }
Meu código ainda possui uma falha: se você se deparar com um Border (por exemplo), ele não será considerado um Panel, pois só pode alocar um UIElement , enquanto os Panel podem alocar vários. Porem, este border pode conter um Panel.Nway, talvez vc n precise de proucupar cm isso, talvez precise, é cm vc.
- Editado E. Pacheco quinta-feira, 28 de julho de 2011 14:08 Errei o nome de uma classe.
- Sugerido como Resposta E. Pacheco sexta-feira, 29 de julho de 2011 13:41
-
sexta-feira, 29 de julho de 2011 13:35Moderador
Manoel,
As opções dadas pelo Américo e pelo E. Pacheco são simples e válidas, mas há uma forma um pouco mais genérica de fazer esse tipo de busca nos objetos da tela, usando uma classe chamada VisualTreeHelper. Essa classe permite que você faça buscas na árvore visual da aplicação, tanto pra cima quanto para baixo.
Eu criei a função abaixo para facilitar ainda mais o uso dessa classe.
public static T[] SearchUIElements<T>(UIElement root, int maxlevel = int.MaxValue, int level = 0) where T : UIElement { var result = new List<T>(); if (root != null) { if (root is T) { result.Add(root as T); } if (level < maxlevel) { var childrencount = VisualTreeHelper.GetChildrenCount(root); DependencyObject child; for (var i = 0; i < childrencount; i++) { child = VisualTreeHelper.GetChild(root, i); if (child is UIElement) { result.AddRange(SearchUIElements<T>(child as UIElement, maxlevel, level + 1)); } } } } return result.ToArray(); }
Suponhamos que você tenha o seguinte XAML:
<Grid x:Name="LayoutRoot" Background="White"> <TextBox /> <TextBox /> <Grid> <TextBox /> <TextBox /> <Grid> <TextBox /> </Grid> </Grid> </Grid>
Podemos usar a função das seguintes formas:
TextBox[] textboxes = SearchUIElements<TextBox>(LayoutRoot); //acha TODOS os 5 campos TextBox textboxes = SearchUIElements<TextBox>(LayoutRoot, 1); //acha apenas os 2 campos TextBox de LayoutRoot textboxes = SearchUIElements<TextBox>(LayoutRoot, 2); //acha 4. Os 2 acima e os 2 que estão no primeiro Grid filho TextBlock[] textblocks = SearchUIElements<TextBlock>(LayoutRoot); //não acha nada, mas procura por TODOS campos TextBlock
Essa é uma função genérica, capaz de achar qualquer tipo de controle na tela. Essa função é executada de forma recursiva até que não existam mais filhos na arvore visual ou até atingir o nível hierárquico máximo passado no segundo parâmetro (que é opcional). O resultado dessa função será um array do tipo de controle solicitado. Sempre será retornado um array, mesmo que seja vazio.
Mas eu fiquei com uma dúvida: Para que você precisa achar todos os campos TextBox dessa ChildWindow? Qual é exatamente a sua necessidade? Estou perguntando isso pois se você estiver fazendo essa varredura para ler os valores dos campos, a melhor forma seria usar Binding e não manipular a tela. Quanto menos o seu código souber sobre a estrutura da tela, mais fácil será de dar manutenção na aplicação no futuro. Sim, há várias situações onde realmente é necessário fazer algum tipo de varredura na tela ou manipular os controles diretamente, mas quanto menos fizermos isso, melhor.
Se voce quiser elaborar mais sobre o assunto, estou a disposição para ajudar a encontrar a melhor solução para o seu problema.
Atenciosamente,
Kelps Leite de Sousa | MVP Silverlight
blog: http://kelps.net
twitter : http://twitter.com/kelps
Não se esqueça de "marcar como resposta" o ítem que lhe ajudou.
- Sugerido como Resposta E. Pacheco sexta-feira, 29 de julho de 2011 13:40
- Editado Kelps Leite de SousaMVP, Moderator sexta-feira, 29 de julho de 2011 16:00 melhoria na função (verificação de nulo)
- Marcado como Resposta Manoel Bruno P. Lima segunda-feira, 29 de agosto de 2011 19:28
-
sexta-feira, 29 de julho de 2011 13:40Excelente, excelente.

