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






3.33/5 (4投票s)
UserControl 填充 ItemsControl – 从内部 UserControl 操作 ItemsControl 集合。
引言
我遇到一个问题:在一个特定的 Silverlight 页面上,我需要取消展开所有 Expander
,除了用户选择展开的 Expander
。 在网上搜索了很久,没有找到解决方案,所以我不得不深入研究并使其工作。
这就是我最终的方案,我认为它足够好可以分享。 我只是为命名空间、类、方法和变量的命名道歉,因为它们使用了我自己的语言(大多数时候!)。 UserControl
的内容和数据对于每个项目都非常具体,所以我只会展示所需的信息以提高清晰度。
背景
总体解决方案是一个父控件,一个 ScrollViewer
,包含一个 StackPanel
。 在其中,ItemsControl
的 ItemTemplate
是一个 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
类和一个递归方法来循环遍历子集合,查找与我们正在查找的类型匹配的子集合。
它返回一个包含所有这些子集合的集合(如果有的话),并且可以在该集合上执行任何想要或需要执行的操作。
希望对某人有所帮助。