【问题标题】:Silverlight - Get the ItemsControl of a DataTemplateSilverlight - 获取 DataTemplate 的 ItemsControl
【发布时间】:2011-01-21 20:04:34
【问题描述】:

我有一个使用 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)。当该事件被触发时,我想获取作为此 TextBox 容器的 ItemsControl 元素。如何从我的事件处理程序中获取 ItemsControl?

请注意:因为 ItemsControl 在 DataGrid 的 DataTemplate 中,我不相信我可以添加一个 x:Name 并从我的代码隐藏中引用它。或者有什么办法吗?

谢谢!

【问题讨论】:

  • 你能告诉我为什么你需要引用 ItemsControl 我觉得这里可能隐藏了一个更好的整体解决方案。

标签: silverlight


【解决方案1】:

使用 ItemsControl.ItemsControlFromItemContainerVisualTreeHelper.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);

您可能还想在 Web 上搜索 VisualTreeHelper 递归函数,以使其中一些更容易。

【讨论】:

    【解决方案2】:

    我喜欢在我的应用程序某处的静态类中使用这个小扩展方法:-

    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();
    

    【讨论】:

    • 经过大量搜索后偶然发现了这一点。当第一个 ComboBox 索引更改时,我试图弄清楚如何连续更新第二个 ComboBox。这将使我很容易找到父 DataGridRow 以及随后在同一行中的第二个 ComboBox。谢谢!
    【解决方案3】:

    不确定这是否适用,但这会使用相同的原理创建一个“切换按钮栏”。

    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);
        }
    }
    }
    

    【讨论】:

      【解决方案4】:

      这是一个捕获包含您的 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;
                  }
              }
      

      希望对你有帮助。

      【讨论】:

        猜你喜欢
        • 2015-09-14
        • 2011-09-11
        • 1970-01-01
        • 2016-08-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多