www
<Menu x:Name="menuTop" ItemsSource="{Binding Path=QueryEditorMenu}"> <Menu.ItemContainerStyle> <Style TargetType="MenuItem"> <Setter Property="Header" Value="{Binding Title}"></Setter> <Setter Property="Command" Value="{Binding Command}"></Setter> <Setter Property="CommandParameter" Value="{Binding NameSpace}"></Setter> <Setter Property="Tag" Value="{Binding Tag}"></Setter> <Setter Property="ItemsSource" Value="{Binding SubItems}"></Setter> <Setter Property="InputGestureText" Value="{Binding ShortcutKey}" /> </Style> </Menu.ItemContainerStyle> </Menu>
public class MenuBar:BindableBase { private string _icon; public string Icon { get { return _icon; } set { SetProperty(ref _icon, value); } } private string _tag; public string Tag { get { return _tag; } set { SetProperty(ref _tag, value); } } private string title; /// <summary> /// 菜单标题 /// </summary> public string Title { get { return title; } set { title = value; } } private string shortcutKey; /// <summary> /// 菜单快捷键 /// </summary> public string ShortcutKey { get { return shortcutKey; } set { shortcutKey = value; } } private string nameSpace; /// <summary> /// 命名空间 /// </summary> public string NameSpace { get { return nameSpace; } set { nameSpace = value; } } private bool _isEnabled; public bool IsEnabled { get { return _isEnabled; } set { SetProperty(ref _isEnabled, value); } } private Visibility _mainViewButtonVisible; public Visibility MainViewButtonVisible { get { return _mainViewButtonVisible; } set { SetProperty(ref _mainViewButtonVisible, value); } } private ObservableCollection<MenuBar> subItems; public ObservableCollection<MenuBar> SubItems { get { return subItems; } set { subItems = value; this.RaisePropertyChanged(); } } private ICommand command; public ICommand Command { get { return command; } set { command = value; this.RaisePropertyChanged(); } } }
private void LoopItemsControl(object child)
{
ItemsControl itemsControl = child as ItemsControl;
for (int i = 0; i < itemsControl.Items.Count; i++)
{
DependencyObject dependencyObject = itemsControl.ItemContainerGenerator.ContainerFromIndex(i);
LoadControlsInXAMLContainer(dependencyObject);
LoopItemsControl(dependencyObject);
}
//if (child is ItemsControl)
//{
// ItemsControl itemsControl = child as ItemsControl;
// for (int i = 0; i < itemsControl.Items.Count; i++)
// {
// LoadControlsInXAMLContainer(itemsControl.ItemContainerGenerator.ContainerFromIndex(i));
// LoopItemsControl(itemsControl.ItemContainerGenerator.ContainerFromIndex(i));
// }
//}
}
foreach (object child in LogicalTreeHelper.GetChildren(dep))
{
if (child is ItemsControl)
{
LoopItemsControl(child);
//ItemsControl itemsControl = child as ItemsControl;
//for (int i = 0; i < itemsControl.Items.Count; i++)
//{
// DependencyObject dependencyObject = itemsControl.ItemContainerGenerator.ContainerFromIndex(i);
// LoadControlsInXAMLContainer(dependencyObject);
//}
//LoopItemsControl(child);
}
LoadControlsInXAMLContainer(child);
}
//修改后 private void LoopItemsControl(object child) { ItemsControl itemsControl = child as ItemsControl; for (int i = 0; i < itemsControl.Items.Count; i++) { DependencyObject dependencyObject = itemsControl.ItemContainerGenerator.ContainerFromIndex(i); if (dependencyObject != null) { //LoadControlsInXAMLContainer(dependencyObject); DependencyObject dependencyObject1 = itemsControl.ItemContainerGenerator.ContainerFromIndex(0); LoadControlsInXAMLContainer(dependencyObject1); DependencyObject dependencyObject2 = ((ItemsControl) dependencyObject1).ItemContainerGenerator.ContainerFromIndex(i); LoadControlsInXAMLContainer(dependencyObject2); if (true) { } //foreach (object items in LogicalTreeHelper.GetChildren(dependencyObject)) //{ // LoadControlsInXAMLContainer(items); //} } //LoopItemsControl(dependencyObject); //for (int j = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); j++) //{ // var child1 = VisualTreeHelper.GetChild(dependencyObject, i); // LoadControlsInXAMLContainer(child1); //} } }
ItemContainerGenerator.ContainerFromIndex(i)
是用来获取与 ItemsControl 的项关联的容器的。在许多情况下,例如 ListBox 或 ComboBox 等控件,这是获取实际元素的有效方式。
然而,对于 Menu 和 MenuItem,情况有些不同。MenuItem 的子项,即子菜单,不会立即生成其容器。当 MenuItem 首次展开时,WPF 才会为子项生成 MenuItem 容器。如果你试图在 MenuItem 首次展开之前使用 ItemContainerGenerator.ContainerFromIndex(i) ,你可能会收到 null,因为子 MenuItem 的容器还没有被生成。
因此,对于 MenuItem,最可靠的方式是直接遍历其 Items 集合,就像我在之前的回答中所展示的那样。这将确保你能访问所有子 MenuItem,无论它们的容器是否已被生成。
这是 WPF 菜单系统的一种特性,以提高性能。只有当用户实际需要看到或交互 with 子菜单时,WPF 才会为其生成容器。