Как динамически заполнить MenuItem во время выполнения с помощью MenuItems? - PullRequest
1 голос
/ 11 марта 2020

У меня есть следующая (упрощенная) модель представления:

public class ViewModel
{
    ObservableCollection<RackViewModel> Racks { get; set; }
}

public class RackViewModel
{
    public string Header { get; set; }

    public ICommand ActivateCommand { get; }

    public ICommand ShowInfoCommand { get; }
}

Конечно, классы модели представления реализуют INotifyPropertyChanged, которую я для краткости опускаю. Я хочу отобразить стойки в строке меню окна. Я попробовал это так:

<Menu DockPanel.Dock="Top">
<MenuItem Header="Racks">
                <ItemsControl ItemsSource="{Binding Racks}">
                    <ItemsControl.ItemTemplate>
                        <ItemContainerTemplate>
                            <MenuItem Header="{Binding Header}">
                                <MenuItem Command="{Binding ActivateCommand}" Header="Activate"/>
                                <MenuItem Command="{Binding ShowInfoCommand}" Header="Show Information"/>
                            </MenuItem>
                        </ItemContainerTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </MenuItem>
</Menu>

Это дает мне следующий результат:

enter image description here

Когда я наведите курсор мыши над В меню все элементы отмечены одновременно, и я не могу получить доступ к подменю. Я ожидал, что это будет следующим:

enter image description here

Кто-нибудь знает, что я сделал не так?

1 Ответ

0 голосов
/ 11 марта 2020

Вы можете использовать ItemSource Свойство

Выглядеть примерно так:

    <Menu>
        <MenuItem Header="Click me" Command="{Binding ChangeCommand}"></MenuItem>
        <MenuItem Header="Items" ItemsSource="{Binding Items}">
            <MenuItem.ItemContainerStyle>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Header" Value="{Binding Header}"></Setter>
                    <Setter Property="ItemsSource" Value="{Binding Children}"></Setter>
                    <Setter Property="Command" Value="{Binding Command}"></Setter>
                </Style>
            </MenuItem.ItemContainerStyle>
        </MenuItem>
    </Menu>

и ваш ViewModel может выглядеть так:

public class MainWindowViewModel
{
    public MainWindowViewModel()
    {
        Items = new ObservableCollection<MenuItem>();
        ChangeCommand = new RelayCommand(ChangeCollection);
        SomethingCommand = new RelayCommand(DoSomething);
    }

    private void DoSomething()
    {
        MessageBox.Show("Hello World");
    }

    private void ChangeCollection()
    {
        this.Items.Clear();

        Items.Add(new MenuItem{Header = "Test 1"});
        Items.Add(new MenuItem{Header = "Test 2", Command = SomethingCommand});
        Items.Add(new MenuItem{Header = "Test 3"});
    }

    public RelayCommand SomethingCommand {get; set;}
    public RelayCommand ChangeCommand { get; set; }

    public ObservableCollection<MenuItem> Items { get; set; }
}

Класс MenuItem :

public class MenuItem
{
    public MenuItem()
    {
        Children = new ObservableCollection<MenuItem>();
    }
    public string Header { get; set; }
    public ObservableCollection<MenuItem> Children { get; set; }
    public ICommand Command { get; set; }
}

Чтобы добавить дочерние элементы, просто выберите MenuItem, который хотите изменить дочерние элементы, и добавьте или удалите это свойство MenuItem.Children.

...