Как динамически добавлять MenuItems (с заголовком) в меню WPF

[Edit # 3] - всем, кто читает этот вопрос: не не ни при каких обстоятельствах используйте подход, описанный в этом вопросе. Это ужасающий кодекс . Я открыто признаю это, зная, что все программисты в прошлом загнали себя в угол, и (особенно при изучении новой технологии) мы все были сбиты с толку другими, благонамеренными разработчиками в сети. Сначала прочтите ответ Роберта, а затем прочтите этот вопрос. Пожалуйста.

[Edit # 2b]

Прошу прощения за объем этого вопроса - здесь есть вопрос (в конце!), Но я хотел убедиться, что исходный код был явным. В любом случае.

[Edit # 2] - заголовок вопроса изменен для более точного отражения ... вопроса.

[Edit] - Я обновил еще немного истории о том, как я оказался в дизайне / коде, который я сделал здесь: Обязательное сообщение в блоге . Если это поможет прояснить вопрос ниже, не стесняйтесь его читать ...

Исходный вопрос

Приложение, над которым я работаю, использует Prism и WPF с рядом модулей (в настоящее время 3), один из которых является хостом меню приложения. Первоначально меню было статическим, с перехватчиками CompositeCommand / DelegateCommands, которые отлично работали для маршрутизации нажатий кнопок соответствующему докладчику. Каждый MenuItem использовал StackPanel в своем заголовке для отображения содержимого в виде комбинации изображения и текстовой метки - это был тот вид, к которому я стремился:


                
                    
                        
                            
                            
                        
                    
                    
                        
                            
                                
                                
                            
                        
                    
                
                
                    
                        
                            
                            
                        
                    
                               
            

К сожалению, приложение стало немного сложнее, и желательно, чтобы другие модули регистрировались в меню - следовательно, я искал возможность сделать меню динамическим. Цель состоит в том, чтобы другие модули (через службу) могли добавлять команды в меню по своему усмотрению - например, модуль A добавит пункт меню в модуль панели инструментов, который вызывает обработчик в модуле A. Есть несколько отличных статей по этой теме - я рассмотрел два: Создание меню WPF с привязкой к данным с использованием шаблона HierarchicalDataTemplate и Пример серии WPF - Пример меню HierarchicalDataTemplate с привязкой к данным . Следуя совету в статье, мне удалось создать динамически построенное меню без очевидных проблем с привязкой данных - оно может создавать меню с элементами, связанными с моей моделью презентации, отражение структуры ObservableCollection в модели представления

В настоящее время мой XAML выглядит следующим образом:


    
        
        
            
        
    
    
        
    
        
        
    

Код, стоящий за представлением, выполняет тяжелую работу в методе ContentPresenter_Loaded:

   private void ContentPresenter_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
    ContentPresenter presenter = sender as ContentPresenter;
    if (sender != null)
    {
        DependencyObject parentObject = VisualTreeHelper.GetParent(presenter);
        bool bContinue = true;
        while (bContinue
            || parentObject == null)
        {
            if (parentObject is MenuItem)
                bContinue = false;
            else
                parentObject = VisualTreeHelper.GetParent(parentObject);
        }
        var menuItem = parentObject as MenuItem;
        if (menuItem != null)
        {
            ToolbarObject toolbarObject = menuItem.DataContext as ToolbarObject;
            StackPanel panel = new StackPanel();
            if (!String.IsNullOrEmpty(toolbarObject.ImageLocation))
            {
                Image image = new Image();
                image.Height = 24;
                image.VerticalAlignment = System.Windows.VerticalAlignment.Center;
                Binding sourceBinding = new Binding("ImageLocation");
                sourceBinding.Mode = BindingMode.TwoWay;
                sourceBinding.Source = toolbarObject;
                image.SetBinding(Image.SourceProperty, sourceBinding);
                panel.Children.Add(image);
            }
            ContentPresenter contentPresenter = new ContentPresenter();
            Binding contentBinding = new Binding("Name");
            contentBinding.Mode = BindingMode.TwoWay;
            contentBinding.Source = toolbarObject;
            contentPresenter.SetBinding(ContentPresenter.ContentProperty, contentBinding);
            panel.Children.Add(contentPresenter);
            menuItem.Header = panel;
            Binding commandBinding = new Binding("Command");
            commandBinding.Mode = BindingMode.TwoWay;
            commandBinding.Source = toolbarObject;
            menuItem.SetBinding(MenuItem.CommandProperty, commandBinding);                    
        }
    }
}

Как вы можете видеть, я ' m пытается воссоздать комбинацию StackPanel / Image / Name исходного меню, просто делая это в коде позади. Попытка сделать это не увенчалась успехом - хотя объекты меню, безусловно, создаются, они не «отображаются» как что-либо, кроме пустых, интерактивных объектов - StackPanel, Image, Name и т. Д. Не отображаются. . Интересно, что это также приводит к стиранию исходного текста в ContentPresent в HierarchicalDataTemplate.

Тогда возникает вопрос, есть ли способ установить MenuItem ' s Свойство Header в событии Load, чтобы оно правильно отображалось в UserControl? Является ли тот факт, что элементы в заголовке не отображаются, свидетельствует о проблеме DataBinding? Если да, то как правильно привязать заголовок к временному объекту (StackPanel, который был создан в обработчике события загрузки)?

Я готов изменить что-либо в приведенном выше коде - это все своего рода создание прототипов, попытка найти лучший способ создания динамического меню. Спасибо!

9
задан Matt Jordan 26 December 2010 в 01:02
поделиться