如何使用 DataTemplate 访问列表框中的特定项目?
我有一个 ListBox,其中包含一个带有 2 个 StackPanel 的 ItemTemplate。 我想访问的第二个 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;
}
I have a ListBox including an ItemTemplate with 2 StackPanels.
There is a TextBox in the second StackPanel i want to access.
(Change it's visibility to true and accept user input)
The trigger should be the SelectionChangedEvent. So, if a user clicks on an ListBoxItem, the TextBlock gets invisible and the TextBox gets visible.
XAML CODE:
<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>
I guess there are several ways to solve this, but nothing I tried worked.
My current approach looks like this
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
谢谢你们的帮助!终于我明白了。解决了 VisualTreeHelper 的问题。多么棒的函数^^
helperFunction
Thank you for your help guys!! Finally i got it. Solved the problem with the VisualTreeHelper. What a great function ^^
helperFunction
使用此编辑功能,您还可以按名称搜索控件(从 VB.NET 转换而来):
With this edited function you can also search for control by name (its converted from VB.NET):
我无法给你一个完整的答案...
但我认为你可以使用 VisualTreeHelper 来迭代任何控件的子级
http://blogs.msdn.com/b/kmahone /archive/2009/03/29/visualtreehelper.aspx
但是,对于您正在寻找的效果,那么我认为使用 SelectedItem 样式可能是一个更好的解决方案 - 例如,请参阅这篇文章 - http://joshsmithonwpf.wordpress.com/2007/07/ 30/自定义列表框中选定的项目/
I can't give you a complete answer...
But I think you can use the VisualTreeHelper to iterate through the children of any control
http://blogs.msdn.com/b/kmahone/archive/2009/03/29/visualtreehelper.aspx
However, for the effect you are looking for, then I think using the SelectedItem Style might be a better solution - e.g. see this article - http://joshsmithonwpf.wordpress.com/2007/07/30/customizing-the-selected-item-in-a-listbox/
使用
ItemContainerGenerator
。Use
ItemContainerGenerator
.由于 DataTemplate 是一个通用模板,可以在代码中多次使用,因此无法通过名称 (x:Name="numberTextBox") 访问它。
我通过创建控件集合解决了与此类似的问题 - 在填充列表框时,我将文本框控件添加到集合中。
直到我找到了更好的灵魂 - 标签属性。在 ListboxItem 中,将 Tag 属性绑定到名称
并访问它
Since DataTemplate is a generic template that could be used many times in the code, there is no way to access it by name (x:Name="numberTextBox").
I solved similar problem to this by making a collection of Controls - while Listbox was populating I add Textbox control to the collection.
Till I found a better soultion - Tag property. In your ListboxItem you bind Tag property to the name
and the to access it