65.9K
CodeProject 正在变化。 阅读更多。
Home

UserControl 填充 ItemsControl – 从内部 UserControl 操作 ItemsControl 集合

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.33/5 (4投票s)

2012年5月23日

CPOL

2分钟阅读

viewsIcon

17777

UserControl 填充 ItemsControl – 从内部 UserControl 操作 ItemsControl 集合。

引言

我遇到一个问题:在一个特定的 Silverlight 页面上,我需要取消展开所有 Expander,除了用户选择展开的 Expander。 在网上搜索了很久,没有找到解决方案,所以我不得不深入研究并使其工作。

这就是我最终的方案,我认为它足够好可以分享。 我只是为命名空间、类、方法和变量的命名道歉,因为它们使用了我自己的语言(大多数时候!)。 UserControl 的内容和数据对于每个项目都非常具体,所以我只会展示所需的信息以提高清晰度。

背景 

总体解决方案是一个父控件,一个 ScrollViewer,包含一个 StackPanel。 在其中,ItemsControlItemTemplate 是一个 UserControl 类型,绑定到 ItemsControl.ItemsSource。 每当用户展开其中一个子 Expander 时,子 UserControl 会触发一个事件,该事件被父控件捕获,然后处理对子集合执行的任何操作。 问题是 StackPanel 的子集合是一个 ItemsControl,我需要访问其中的 Expander

使用代码 - 将事件传递给父控件

UserControl - myTema 

UserControl myTema 基本上是一个 Expander,其中包含一些消耗绑定数据的内容(在我的例子中,是一个 HeaderTemplate 和一堆嵌套的 UserControl,对于这个解释来说不需要)。 并且有一个操作到 Expanded 事件:

<Grid x:Name="LayoutRoot" >
  <toolkit:Expander x:Name="ExpanderTema" Expanded="ExpanderTema_Expanded" 
            HeaderTemplate="{StaticResource ExpanderTemaDataTemplate}" 
            Header="{Binding myTema_Conteudo, ElementName=myTemaRoot}" >
    <StackPanel x:Name="stackSugest" >
      <!-- Controls that hold the data -->
    </StackPanel>
  </toolkit:Expander>
</Grid>
public event EventHandler ExpanderTemaExpanded;

private void ExpanderTema_Expanded(object sender, System.Windows.RoutedEventArgs e)
{
    ExpanderTemaExpanded(sender, null);
}

ParentControl

StackPanel 父控件的 ItemsControl.ItemsSource 基于一个局部变量,并捕获其 UserControl 子控件中的 ExpanderTemaExpanded 事件。

List<myTema_Info> ListTema = new List<myTema_Info>();
itemsMyTemas.ItemsSource = ListTema; 
<ScrollViewer x:Name="ScrollViewer1" >
  <Grid>
    <StackPanel x:Name="stackMyTemas" >
      <ItemsControl x:Name="itemsMyTemas" >
        <ItemsControl.ItemTemplate>
          <DataTemplate>
            <componente:myTema x:Name="myCategory_Temas" 
                ExpanderTemaExpanded="myCategory_Temas_ExpanderTemaExpanded" 
                myTema_Conteudo="{Binding}" />
          </DataTemplate>
        </ItemsControl.ItemTemplate>
      </ItemsControl>
    </StackPanel>
  </Grid>
</ScrollViewer>

在由 USerControl 调用的方法中,ExpanderTemaExpanded 事件是发生魔术的地方,使用了下一节中解释的 GetAllChildFrameworkElement 函数。

private void myCategory_Temas_ExpanderTemaExpanded(object sender, System.EventArgs e) 
{ 
  var found = Tools.GetAllChildFrameworkElement(stackMyTemas, typeof(Expander));
  foreach (Expander item in found)
  {
    if (item != (Expander)sender) // If item is different from the one that originated the call 
      item.IsExpanded = false; // Do something to it (my case, unexpand) 
  }
} 

使用代码 - 通用静态类

在我的例子中,我使用一个通用的 static 类,其中我放置所有通用函数,例如查找父 StackPanel 子集合中所有 Expander 所需的函数。

public static class Tools
{
  public static List<FrameworkElement> GetAllChildFrameworkElement(
         FrameworkElement parentElement, Type typeRequired)
  {
     List<FrameworkElement> childFrameworkElementFound = 
                                  new List<FrameworkElement>();
     SearchAllChildFrameworkElement(parentElement, childFrameworkElementFound, typeRequired);
     return childFrameworkElementFound;
  }

  private static void SearchAllChildFrameworkElement(FrameworkElement parentFrameworkElement, 
          List<FrameworkElement> allChildFrameworkElement, Type typeRequired)
  {
    int childrenCount = VisualTreeHelper.GetChildrenCount(parentFrameworkElement);
    if (childrenCount > 0)
    {
      for (int i = 0; i < childrenCount; i++)
      {
        FrameworkElement childFrameworkElement = 
           (FrameworkElement)VisualTreeHelper.GetChild(parentFrameworkElement, i);
        if (childFrameworkElement.GetType().Equals(typeRequired))
        {
          allChildFrameworkElement.Add(childFrameworkElement);
        }

        SearchAllChildFrameworkElement(childFrameworkElement, 
                  allChildFrameworkElement, typeRequired);
      }
    }
  }
}

我从 http://forums.silverlight.net/t/160356.aspx 找到了这段代码。

它使用了 VisualTreeHelper 类和一个递归方法来循环遍历子集合,查找与我们正在查找的类型匹配的子集合。

它返回一个包含所有这些子集合的集合(如果有的话),并且可以在该集合上执行任何想要或需要执行的操作。

希望对某人有所帮助。

© . All rights reserved.