2012-08-15 70 views
0

我已经在WPF中获得了如下列XAML中的列表框。它充满了ListBoxItems,其中有一个复选框和一个标签。我的顶部项目之一是“全选”选项。当我点击全选选项时,我有一个遍历所有列表框项目的处理程序,它应该检查所有其他列表框子项目上的所有复选框。问题在于它只做可见的子项,当它遇到不可见的listboxitems时,VisualTreeHelper在查找特定类型的对象(如CheckBox)时似乎返回null。似乎VisualTreeHelper在这里似乎有问题。我用错了吗?任何帮助赞赏。另一个细节 - 如果我滚动并查看所有listboxitems至少一次,它工作正常。从列表框中获取子项无法获取未被查看的子项

MJ

XAML - 一个简单的列表框具有一吨的儿童(仅出于简洁显示的第一子)

<ListBox Grid.Row="0" Margin="0,0,0,0" Name="CharacterListBox"> 
     <ListBoxItem> 
      <StackPanel Orientation="Horizontal"> 
       <CheckBox HorizontalAlignment="Center" VerticalAlignment="Center" Click="AllCharactersClicked"></CheckBox> 
       <Label Padding="5">All Characters</Label> 
      </StackPanel> 
     </ListBoxItem> 

C# - 两个功能,首先是其将向所述对象的辅助方法树使用VisualTreeHelper(我在一些网站上发现了这个)。第二个函数是“全选”listboxitem的点击处理程序。它遍历所有孩子并尝试检查所有复选框。

private T FindControlByType<T>(DependencyObject container, string name) where T : DependencyObject 
    { 
     T foundControl = null; 

     //for each child object in the container 
     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(container); i++) 
     { 
      //is the object of the type we are looking for? 
      if (VisualTreeHelper.GetChild(container, i) is T && (VisualTreeHelper.GetChild(container, i).GetValue(FrameworkElement.NameProperty).Equals(name) || name == null)) 
      { 
       foundControl = (T)VisualTreeHelper.GetChild(container, i); 
       break; 
      } 
      //if not, does it have children? 
      else if (VisualTreeHelper.GetChildrenCount(VisualTreeHelper.GetChild(container, i)) > 0) 
      { 
       //recursively look at its children 
       foundControl = FindControlByType<T>(VisualTreeHelper.GetChild(container, i), name); 
       if (foundControl != null) 
        break; 
      } 
     } 

     return foundControl; 
    } 

    private void AllCharactersClicked(object sender, RoutedEventArgs e) 
    { 

     MainWindow.Instance.BadChars.Clear(); 

     int count = 0; 
     foreach (ListBoxItem item in CharacterListBox.Items) 
     { 
      CheckBox cb = FindControlByType<CheckBox>(item, null);     
      Label l = FindControlByType<Label>(item, null); 
      if (cb != null && l != null) 
      { 
       count++; 
       cb.IsChecked = true; 

       if (cb.IsChecked == true) 
       { 
        string sc = (string)l.Content; 
        if (sc.Length == 1) 
        { 
         char c = Char.Parse(sc); 
         MainWindow.Instance.BadChars.Add(c); 
        } 
       } 
      } 

     } 

    } 
+3

你应该考虑使用绑定而不是走视觉树。 – sam1589914 2012-08-15 13:51:32

+1

只需快速了解您遇到的情况;该列表框使用虚拟化堆叠面板(sp),仅根据需要分配视觉控件(出于效率原因)。这意味着可能会或可能不会分配控制权来遍历视觉树,以随意进行数据操作(这不是视觉树的目标)。正如其他人所说的,绑定是要走的路。 – Alternator 2012-08-16 02:40:35

回答

3

那些遍布整个地方的视觉树行走方法都是瘟疫。你应该几乎从不需要这些。

只需结合ItemsSource到包含用于CheckBoxes属性的对象的列表,创建data templateItemTemplate)和bind该属性到CheckBox。在代码中,只需遍历绑定到ItemsSource的集合并设置porperty。