MenuItem, добавленный программно, вызывает ошибку Binding
У меня есть главное меню mnuMainMenu
состоящий из нескольких подменю. Одно из подменю mnuMostRecentDirs
само по себе является другим меню, элементы которого генерируются во время выполнения с использованием свойства ItemSource, связанного с коллекцией ObservableCollection. По сути, он отображает список самых последних использованных папок.
Проблема заключается в том, что добавленные MenuItems динамически генерируют следующую ошибку привязки данных:
Ошибка System.Windows.Data: 4: Не удается найти источник для привязки со ссылкой 'RelativeSource FindAncestor, AncestorType =' System.Windows.Controls.ItemsControl ', AncestorLevel =' 1 ''. BindingExpression: Path = HorizontalContentAlignment; DataItem = NULL; Целевым элементом является "MenuItem" (Name = ''); Свойство target - "HorizontalContentAlignment" (тип "HorizontalAlignment")
Декларация XAML главного меню выглядит примерно так:
<!-- Main Menu -->
<Menu x:Name="mnuMainMenu" Height="Auto" IsMainMenu="True">
<!--- ... more menu declarations before ... -->
<MenuItem x:Name="mnuitemWorkDirs" Header="Directories">
<MenuItem x:Name="mnuNewDir"
Header="New"
Style="{StaticResource MenuItem}"
Command="{x:Static cmds:Commands.NewDirectory}" />
<MenuItem x:Name="mnuCurrentDir"
Header="Current"
Style="{StaticResource MenuItem}"
Command="{x:Static cmds:Commands.CurrentDirectory}" />
<MenuItem x:Name="mnuMostRecentDirs"
Header="Recent Directories.."
Style="{StaticResource MenuItem}"
ItemsSource="{Binding ElementName=theMain, Path=MostRecentFoldersList}" />
</MenuItem>
<!--- ... more menu declarations after ... -->
</Menu>
А следующий код добавляет папки в наблюдаемую коллекцию во время выполнения:
private void PopulateMostRecentFoldersList(string[] paths)
{
MostRecentFoldersList.Clear();
if (paths == null)
return;
foreach (var fullPath in paths)
{
var mi = new MenuItem();
mi.Command = Commands.ChooseWorkingDirectory;
mi.CommandParameter = fullPath;
string name = System.IO.Path.GetFileName(fullPath);
mi.Header = name.ToUpper();
// removing this style completely
// or manually setting the HorizontalContentAlignment property here
// prevents the binding error from happening
mi.Style = (Style)FindResource("MenuItem");
MostRecentFoldersList.Add(mi);
}
}
Мне удалось отследить проблему с привязкой, объявленной в стиле для MenuItem, который не объявлен в моем приложении. Я предполагаю, что это стиль по умолчанию для пунктов меню..
Похоже, что ни у одного из других пунктов меню нет проблем с привязкой к тому же стилю, который применяется ко всем.
Поэтому я думаю, что проблема заключается в моем подходе к динамическому добавлению MenuItems. Более конкретно, кажется, что стиль применяется к MenuItem до того, как элемент добавляется в ItemsControl.
До сих пор я мог придумать только установку свойства HorizontalContentAlignment в коде на MenuItem до добавления его в наблюдаемую коллекцию, но это всего лишь пластырь, и он действительно маскирует реальную проблему.
2 ответа
Как указывает @LPL - оказывается, это известная (признанная) проблема в структуре WPF. Основываясь на информации, найденной на форумах поддержки MSDN здесь и здесь, кажется, что при установке ItemsSource для MenuItem в коллекцию MenuItem, он не обрабатывает вещи в правильном порядке.
За MSDN Вспомогательный персонал:
Это происходит, когда вы устанавливаете MenuItem.ItemsSource в коллекцию, которая содержит MenuItems. Эта ошибка уже была обработана внутри, так что вы можете просто оставить ее в покое.
Или вы можете явно установить свойство MenuItem.HorizontContentAlignment и свойство VerticalContentAlignment, чтобы избежать этой ошибки. Вы можете просто поместить следующий код в application.Resource для достижения этой цели.
<Style TargetType="MenuItem"> <Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="VerticalContentAlignment" Value="Center"/> </Style>
Я надеюсь, что это помогает другим людям, имеющим ту же проблему.
Я действительно думаю, что не очень хорошая идея или "" совместимость с WPF "- добавлять UIelemnts из кода.
Я хотел бы предложить что-то вроде этого:
<Menu>
<MenuItem Header="MainMenu" Name="sampleMenu">
<MenuItem.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding Path=PathtoNameOfRecentDocObject}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</Menu>
и установите для MainSenu ItemsSource значение MostRecentFoldersList