如何使用DataTemplate访问列表框中的特定项目?

我有一个ListBox,包括一个带有2个StackPanels的ItemTemplate。 我想要访问的第二个StackPanel中有一个TextBox。 (将其可见性更改为true并接受用户输入)触发器应为SelectionChangedEvent。 因此,如果用户单击ListBoxItem,TextBlock将变为不可见,TextBox将变为可见。

XAML代码:

                          

我想有几种方法可以解决这个问题,但我没有尝试过。

我目前的做法是这样的

  private void ContactListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { ListBoxItem listBoxItem = ContactListBox.SelectedItem as ListBoxItem; DataTemplate listBoxTemplate = listBoxItem.ContentTemplate; // How to access the DataTemplate content? StackPanel outerStackPanel = listBoxTemplate.XXX as StackPanel; StackPanel innerStackPanel = outerStackPanel.Children[1] as StackPanel; TextBox nameBox = innerStackPanel.Children[0] as TextBox; TextBlock nameBlock = innerStackPanel.Children[1] as TextBlock; nameBox.Visibility = System.Windows.Visibility.Visible; nameBlock.Visibility = System.Windows.Visibility.Collapsed; } 

谢谢你的帮助! 终于我明白了。 解决了VisualTreeHelper的问题。 多么棒的function^^

 private void ContactListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (ContactListBox.SelectedIndex == -1) return; currentSelectedListBoxItem = this.ContactListBox.ItemContainerGenerator.ContainerFromIndex(ContactListBox.SelectedIndex) as ListBoxItem; if (currentSelectedListBoxItem == null) return; // Iterate whole listbox tree and search for this items TextBox nameBox = helperClass.FindDescendant(currentSelectedListBoxItem); TextBlock nameBlock = helperClass.FindDescendant(currentSelectedListBoxItem); 

helperFunction

 public T FindDescendant(DependencyObject obj) where T : DependencyObject { // Check if this object is the specified type if (obj is T) return obj as T; // Check for children int childrenCount = VisualTreeHelper.GetChildrenCount(obj); if (childrenCount < 1) return null; // First check all the children for (int i = 0; i < childrenCount; i++) { DependencyObject child = VisualTreeHelper.GetChild(obj, i); if (child is T) return child as T; } // Then check the childrens children for (int i = 0; i < childrenCount; i++) { DependencyObject child = FindDescendant(VisualTreeHelper.GetChild(obj, i)); if (child != null && child is T) return child as T; } return null; } 

使用此编辑function,您还可以按名称搜索控件(从VB.NET转换):

 public T FindDescendantByName(DependencyObject obj, string objname) where T : DependencyObject { string controlneve = ""; Type tyype = obj.GetType(); if (tyype.GetProperty("Name") != null) { PropertyInfo prop = tyype.GetProperty("Name"); controlneve = prop.GetValue((object)obj, null); } else { return null; } if (obj is T && objname.ToString().ToLower() == controlneve.ToString().ToLower()) { return obj as T; } // Check for children int childrenCount = VisualTreeHelper.GetChildrenCount(obj); if (childrenCount < 1) return null; // First check all the children for (int i = 0; i <= childrenCount - 1; i++) { DependencyObject child = VisualTreeHelper.GetChild(obj, i); if (child is T && objname.ToString().ToLower() == controlneve.ToString().ToLower()) { return child as T; } } // Then check the childrens children for (int i = 0; i <= childrenCount - 1; i++) { string checkobjname = objname; DependencyObject child = FindDescendantByName(VisualTreeHelper.GetChild(obj, i), objname); if (child != null && child is T && objname.ToString().ToLower() == checkobjname.ToString().ToLower()) { return child as T; } } return null; } 

我不能给你一个完整的答案……

但我认为你可以使用VisualTreeHelper迭代任何控件的子项http://blogs.msdn.com/b/kmahone/archive/2009/03/29/visualtreehelper.aspx

但是,对于您正在寻找的效果,我认为使用SelectedItem样式可能是一个更好的解决方案 – 例如,请参阅此文章 – http://joshsmithonwpf.wordpress.com/2007/07/30/customizing-the-selected-项目-IN-A-列表框/

由于DataTemplate是一个可以在代码中多次使用的通用模板,因此无法通过名称访问它(x:Name =“numberTextBox”)。

我通过制作一组控件解决了类似的问题 – 当Listbox填充时我将Textbox控件添加到集合中。

 string text = myCollectionOfTextBoxes[listbox.SelectedIndex].Text; 

直到我找到了更好的灵魂 – 标签属性。 在ListboxItem中,将Tag属性绑定到名称

 Tag="{Binding Name}" 

并访问它

 ListBoxItem listBoxItem = ContactListBox.SelectedItem as ListBoxItem; string name = listBoxItem.Tag.ToString(); 

使用ItemContainerGenerator

 private void ContactListBox_SelectionChanged (object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count == 1) { var container = (FrameworkElement)ContactListBox.ItemContainerGenerator. ContainerFromItem(e.AddedItems[0]); StackPanel sp = container.FindVisualChild(); TextBox tbName = (TextBox) sp.FindName("tbName"); TextBlock lblName = (TextBlock)sp.FindName("lblName"); TextBlock lblNumber = (TextBlock)sp.FindName("lblNumber"); } }