2012-10-23 7 views
6

MVVMの原則に厳密に従うようにWPFアプリケーションを構築しています。メニューを正しくレンダリングするのに問題があります。私はいくつかのアプローチを試してきました。私の綴りは正しいようですが、スタイルの操作についてはわかりません。WPFメニューバインディングでHierarchicalDataTemplateを使用してもメニュー項目が適切にレンダリングされない

ここに問題があるコードがあります。私が言ったように、それはバインディングが良いと思われ、私はスヌープを使用してヘッダーメニュー項目の正しい値を見ることができますが、私がレンダリングしたものはすべてメニュー項目の空のコンテナです。

private ObservableCollection<MenuViewModel> _topMenuItems; 
    public ObservableCollection<MenuViewModel> TopMenuItems 
    { 
     get { return _topMenuItems; } 
     set 
     { 
      if (_topMenuItems == value) 
       return; 

      _topMenuItems = value; base.RaisePropertyChanged("TopMenuItems"); 
     } 
    } 
... 
    public void LoadMainMenu() 
    { 
     IList<ViewModels.MenuViewModel> fileMenuItems = PopulateFileMenuEntries(); 
     IList<ViewModels.MenuViewModel> editMenuItems = PopulateEditMenuEntries(); 

     _topMenuItems.Add(new ViewModels.MenuViewModel() { MenuText = "_File", Children = new ObservableCollection<ViewModels.MenuViewModel>(fileMenuItems) }); 
     _topMenuItems.Add(new ViewModels.MenuViewModel() { MenuText = "_Edit", Children = new ObservableCollection<ViewModels.MenuViewModel>(editMenuItems) }); 

    private IList<ViewModels.MenuViewModel> PopulateFileMenuEntries() 
    { 
     List<ViewModels.MenuViewModel> fileMenuItems = new List<ViewModels.MenuViewModel>(); 

     fileMenuItems.Add(new ViewModels.MenuViewModel() { MenuText = "_Open", MenuIcon = new BitmapImage(new Uri("pack://application:,,,/Resources/OpenDocument16.png")) , Command = _mainWindowViewModel.OpenCommand }); 
     fileMenuItems.Add(new ViewModels.MenuViewModel() { MenuText = "Open _Recent" }); 

     return fileMenuItems; 
    } 

MenuViewModel:私のメインのViewModelに

<DockPanel> 
     <DockPanel.Resources> 
      <HierarchicalDataTemplate x:Key="TopMenuHDT" ItemsSource="{Binding Children}"> 
       <HierarchicalDataTemplate.ItemContainerStyle> 
        <Style TargetType="{x:Type MenuItem}"> 
         <Setter Property="Command" Value="{Binding Command}" /> 
         <Setter Property="Header" Value="{Binding MenuText}" /> 
         <Setter Property="Icon"> 
          <Setter.Value> 
           <Image Source="{Binding MenuIcon}" Height="16px" Width="16px" /> 
          </Setter.Value> 
         </Setter> 
        </Style> 
       </HierarchicalDataTemplate.ItemContainerStyle> 
      </HierarchicalDataTemplate> 

     </DockPanel.Resources> 
     <Menu DockPanel.Dock="Top" Height="auto" 
       ItemsSource="{Binding TopMenuItems}" 
       ItemTemplate="{StaticResource TopMenuHDT}"/> 

public class MenuViewModel : ObservableObject 
{ 
    internal MenuViewModel() 
    { 
     IsEnabled = true; 
    } 

    private string _menuText; 
    public string MenuText 
    { 
     get { return _menuText; } 
     set 
     { 
      if (_menuText == value) 
       return; 

      _menuText = value; base.RaisePropertyChanged("MenuText"); 
     } 
    } 

    private ICommand _command; 
    public ICommand Command 
    { 
     get { return _command; } 
     set 
     { 
      if (_command == value) 
       return; 

      _command = value; base.RaisePropertyChanged("Command"); 
     } 
    } 

    private BitmapImage _menuIcon; 
    public BitmapImage MenuIcon 
    { 
     get { return _menuIcon; } 
     set 
     { 
      if (_menuIcon == value) 
       return; 

      _menuIcon = value; base.RaisePropertyChanged("MenuIcon"); 
     } 
    } 


    private ObservableCollection<MenuViewModel> _children; 
    public ObservableCollection<MenuViewModel> Children 
    { 
     get { return _children; } 
     set 
     { 
      _children = value; base.RaisePropertyChanged("Children"); 
     } 
    } 
} 

これは正しくレンダリングされ得ることに任意の助けいただければ幸いです。

EDIT:

ここで誰かがこの同様の問題に遭遇した場合の最終的な解決策だ:テンプレートである場合

<DockPanel> 
    <Menu DockPanel.Dock="Top" Height="auto" ItemsSource="{Binding TopMenuItems}" > 
     <Menu.Resources> 
      <Image x:Key="MenuIconResource" Height="16" Width="16" Source="{Binding MenuIcon}" x:Shared="False" /> 
      <Style TargetType="{x:Type MenuItem}"> 
       <Setter Property="Command" Value="{Binding Command}" /> 
       <Setter Property="Header" Value="{Binding MenuText}" /> 
       <Setter Property="InputGestureText" Value="{Binding ShortcutText}" /> 
       <Setter Property="IsEnabled" Value="{Binding IsEnabled}" /> 
       <Setter Property="Icon" Value="{StaticResource MenuIconResource}" /> 
       <Setter Property="ItemsSource" Value="{Binding Children}"/> 

       <Style.Triggers> 
        <DataTrigger Binding="{Binding }" Value="{x:Null}"> 
         <Setter Property="Template" > 
          <Setter.Value> 
           <ControlTemplate> 
            <Separator Style="{StaticResource {x:Static MenuItem.SeparatorStyleKey}}" /> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Menu.Resources> 
    </Menu> 
+1

のこれを試してみてくださいあなたのHierarchicalDataTemplateで?私はあなたがポイントを参照してください – Dtex

+0

定義されたItemContainerStyleを見ることができます。私は間違った方向からこれに近づいていました。それは、最小限の努力でメニューに標準的な外観を維持するために、以下に概説されるカスタムスタイルがより良いアプローチであるようです。 – genus

+0

@genusセパレータをサポートするためにこれを編集する方法はありますか? –

答えて

10

ではなく、あなたのDataTemplate

<DockPanel> 
    <Menu DockPanel.Dock="Top" Height="auto" 
      ItemsSource="{Binding TopMenuItems}"> 

     <Menu.Resources> 
      <Style TargetType="{x:Type MenuItem}"> 
       <Setter Property="Command" Value="{Binding Command}" /> 
       <Setter Property="Header" Value="{Binding MenuText}" /> 
       <Setter Property="Icon"> 
        <Setter.Value> 
         <Image Source="{Binding MenuIcon}" Height="16px" Width="16px" /> 
        </Setter.Value> 
       </Setter> 
       <Setter Property="ItemsSource" Value="{Binding Children}"/> 
      </Style> 
     </Menu.Resources> 

    </Menu> 
</DockPanel> 
+0

はい、ありがとうございます!これは私が必要とするものに非常に近いです。 MenuIcon用に設定された画像が表示されていない点を除いて、正常に動作します。 BitmapImage MenuIconを新しいBitmapImage(新しいUri( "pack:// application:,,,/Resources/OpenDocument16.png"))に設定しています。何か案は? – genus

+0

"Resources/OpenDocument16.png"のような文字列を返すとどうなりますか? – user195275

+0

これはある程度機能します。クリックしたときからアイコンを解決するのにかかる時間が、メニューの開きに遅すぎることがあります。私はすぐに編集の質問に私の解決策を追加します。 – genus

関連する問題