我有一个使用DataGrid的Silverlight应用程序。在DataGrid内部,我有一个DataTemplate,其定义如下:
<Grid x:Name="myGrid" Tag="{Binding}" Loaded="myGrid_Loaded">
<ItemsControl ItemsSource="{Binding MyItems}" Tag="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal" Width="138">
<TextBlock Text="{Binding Type}" />
<TextBox x:Name="myTextBox" TextChanged="myTextBox_TextChanged" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
当用户在TextBox中输入文本时,我有一个必须在此时触发的事件(myTextBox_TextChanged)。当该事件被触发时,我想获得ItemsControl元素,该元素是此TextBox的容器。如何从我的事件处理程序中获取ItemsControl?
请注意:因为ItemsControl在DataGrid的DataTemplate中,我不相信我只能添加一个x:Name并从我的代码隐藏中引用它。或者有办法做到这一点吗?
谢谢!
答案 0 :(得分:4)
使用ItemsControl.ItemsControlFromItemContainer
和VisualTreeHelper.GetParent
的组合,您应该能够找到您的ItemsControl
var txt = sender as TextBox;
var panel1 = VisualTreeHelper.GetParent(txt);
var panel2 = VisualTreeHelper.GetParent(panel1);
var contentPresenter = VisualTreeHelper.GetParent(panel2);
var ic = ItemsControl.ItemsControlFromItemContainer(contentPresenter);
您可能还想在网上搜索VisualTreeHelper递归函数,以便更轻松地实现这一目标。
答案 1 :(得分:4)
我喜欢在我的app中的某个静态类中使用这个小扩展方法: -
public static IEnumerable<DependencyObject> Ancestors(this DependencyObject root)
{
DependencyObject current = VisualTreeHelper.GetParent(root);
while (current != null)
{
yield return current;
current = VisualTreeHelper.GetParent(current);
}
}
有了这个,你应该可以这样做: -
ItemsControl control = ((DependencyObject)sender).Ancestors()
.TypeOf<ItemsControl>().FirstOrDefault();
答案 2 :(得分:0)
不确定这是否适用,但这会使用相同的原则创建“切换按钮栏”。
private void UIClassButton_Click(object sender, RoutedEventArgs e){
Button SenderButton = (Button)sender;
ItemsControl SendersItemControl = ItemsControl.ItemsControlFromItemContainer(VisualTreeHelper.GetParent(SenderButton));
IEnumerable<DependencyObject> DependencyObjectCollection = SendersItemControl.GetContainers();
foreach (ContentPresenter item in DependencyObjectCollection) {
ContentPresenter UIClassPresenter = (ContentPresenter)item;
Button UIClassButton = (Button)UIClassPresenter.GetVisualChildren().First();
if (UIClassButton != SenderButton) {
VisualStateManager.GoToState(UIClassButton, "Normal", true);
}
else {
VisualStateManager.GoToState(UIClassButton, "Pressed", true);
}
}
}
答案 3 :(得分:0)
以下是捕获容纳ItemsControl项目的容器的示例:
CheckBox checkbox = sender as CheckBox;
foreach (var item in MembersItemsControl.Items)
{
var container = MembersItemsControl.ItemContainerGenerator.ContainerFromItem(item) as FrameworkElement;
UserInformation user = container.DataContext as UserInformation;
bool isMale = true;
if (user.sex == isMale && checkbox.IsChecked.Value == true)
{
container.Visibility = System.Windows.Visibility.Visible;
}
}
我希望有所帮助。