以编程方式添加的MenuItem导致绑定错误

时间:2013-01-25 16:44:26

标签: wpf binding styles

我有一个主菜单mnuMainMenu,包含几个子菜单。其中一个子菜单mnuMostRecentDirs本身是另一个菜单,它使用绑定到ObservableCollection的ItemSource属性在运行时生成它的项目。基本上它显示了最近使用的文件夹列表。

问题是添加的MenuItem动态生成以下数据绑定错误:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'HorizontalContentAlignment' (type '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的方法。更具体地说,似乎在将项添加到ItemsControl之前将样式应用于MenuItem。

到目前为止,我只能在将菜单添加到可观察集合之前在MenuItem上设置Horizo​​ntalContentAlignment属性,但这只是一个创可贴,它只是真正掩盖了真正的问题。

2 个答案:

答案 0 :(得分:8)

正如@LPL所指出的 - 事实证明这是WPF框架中已知(已确认)的问题。根据MSDN支持论坛herehere上的信息,似乎将MenuItem的ItemsSource设置为MenuItems的集合时,它不会按正确的顺序处理事情

每个MSDN支持人员:

  

当您将MenuItem.ItemsSource设置为Collection时会发生这种情况   包含MenuItems。此错误已在内部处理,因此   你可以不管它。

     

或者您可以显式设置MenuItem.Horizo​​ntalContentAlignment属性   和VerticalContentAlignment属性,以避免此错误。您可以   只需将以下代码放在application.Resource中即可实现。

  <Style TargetType="MenuItem">
   <Setter Property="HorizontalContentAlignment" Value="Left"/>
   <Setter Property="VerticalContentAlignment" Value="Center"/>
  </Style>

我希望这有助于其他人遇到同样的问题。

答案 1 :(得分:1)

我认为从代码添加UIelemnts不是一个好主意或“”WPF兼容“。

我会建议这样的事情:

    <Menu>
        <MenuItem Header="MainMenu" Name="sampleMenu">
            <MenuItem.ItemTemplate>
                <DataTemplate>
                    <MenuItem Header="{Binding Path=PathtoNameOfRecentDocObject}"/>
                </DataTemplate>
            </MenuItem.ItemTemplate>
        </MenuItem>
    </Menu>

并将MainMenu的ItemsSource设置为MostRecentFoldersList