我有一个包含2个StackPanels的ItemTemplate的ListBox。我要访问的第二个StackPanel中有一个TextBox。(将其可见性更改为true并接受用户输入)触发器应为SelectionChangedEvent。因此,如果用户单击ListBoxItem,则TextBlock变为不可见,而TextBox变为可见。
XAML代码:
<ListBox Grid.Row="1" Name="ContactListBox" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" ItemsSource="{Binding Contacts}" Margin="0,36,0,0" SelectionChanged="ContactListBox_SelectionChanged"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Margin="0,0,0,0"> <toolkit:ContextMenuService.ContextMenu> <toolkit:ContextMenu> <toolkit:MenuItem Header="Edit Contact" Click="ContactMenuItem_Click"/> <toolkit:MenuItem Header="Delete Contact" Click="ContactMenuItem_Click"/> </toolkit:ContextMenu> </toolkit:ContextMenuService.ContextMenu> <Grid> <Rectangle Fill="{StaticResource PhoneAccentBrush}" Width="72" Height="72"> <Rectangle.OpacityMask> <ImageBrush ImageSource="/Images/defaultContactImage.png" Stretch="UniformToFill"/> </Rectangle.OpacityMask> </Rectangle> </Grid> <StackPanel> <TextBox Text="{Binding Name}" TextWrapping="Wrap" Visibility="Collapsed"/> <TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" /> <TextBlock Text="{Binding Number}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextAccentStyle}"/> </StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
我想有几种方法可以解决此问题,但是我没有尝试过。
我目前的做法是这样的
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解决了该问题。多么出色的功能^^
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<TextBox>(currentSelectedListBoxItem); TextBlock nameBlock = helperClass.FindDescendant<TextBlock>(currentSelectedListBoxItem);
辅助功能
public T FindDescendant<T>(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<T>(VisualTreeHelper.GetChild(obj, i)); if (child != null && child is T) return child as T; } return null; }