8

mnuMainMenuいくつかのサブメニューで構成されるメイン メニューがあります。サブメニューの 1 つはmnuMostRecentDirs、ObservableCollection にバインドされた ItemSource プロパティを使用して、実行時にアイテムが生成される別のメニューです。基本的に、最近使用したフォルダーのリストを表示しています。

問題は、動的に追加された MenuItem が次のデータ バインディング エラーを生成することです。

System.Windows.Data エラー: 4 : 参照 'RelativeSource FindAncestor、AncestorType='System.Windows.Controls.ItemsControl'、AncestorLevel='1'' でバインディングのソースが見つかりません。BindingExpression:Path=Horizo​​ntalContentAlignment; DataItem=null; ターゲット要素は 'MenuItem' (Name='') です。ターゲット プロパティは 'Horizo​​ntalContentAlignment' (タイプ 'Horizo​​ntalAlignment') です

メイン メニューの 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 に適用されているようです。

これまでのところ、監視可能なコレクションに追加する前に、コードで Horizo​​ntalContentAlignment プロパティを MenuItem に設定することしかできませんでしたが、それは単なる応急処置であり、実際の問題を実際に隠しているだけです。

4

2 に答える 2

11

@LPLが指摘しているように、これはWPFフレームワークの既知の(認識されている)問題であることがわかります。ここここのMSDNサポートフォーラムで見つかった情報に基づくと、MenuItemのItemsSourceをMenuItemのコレクションに設定すると、正しい順序で処理されないようです。

MSDNサポートスタッフによると:

これは、MenuItem.ItemsSourceをMenuItemsを含むコレクションに設定した場合に発生します。このエラーはすでに内部で処理されているため、そのままにしておくことができます。

または、MenuItem.Horizo​​ntalContentAlignmentプロパティとVerticalContentAlignmentプロパティを明示的に設定して、このエラーを回避することもできます。これを実現するには、次のコードをapplication.Resourceに配置するだけです。

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

これが同じ問題を抱えている他の人に役立つことを願っています。

于 2013-01-25T19:19:01.173 に答える
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

于 2013-01-25T16:53:17.113 に答える