[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, который был создан в обработчике события загрузки)?
Я готов изменить что-либо в приведенном выше коде - это все своего рода создание прототипов, попытка найти лучший способ создания динамического меню. Спасибо!