2010-12-07 2 views
3

J'utilise une commande de menu en tant que région. Cela fonctionne bien, cependant quand j'ajoute un thème à mon application (Ajout d'un dictionnaire de ressources à mon App.xaml) les menus normaux ont le thème, mais les vues dans ma région (qui sont des items de menu) n'ont pas ce thème .Menu comme régions de prisme + problème de thèmes

Quelle pourrait être la raison? Quelqu'un a une idée pour une solution de rechange?

Alex.

+0

peut vous envoyer un échantillon? –

Répondre

1

Cela peut être un bug dans l'adaptateur de région du menu Prism. Je suggère de signaler le problème sur CodePlex.

+0

Cela semble être un problème sans rapport avec le prisme. Si je crée un MenuItem à partir d'un fichier XAML différent, puis l'ajouter à un menu, son apparence est incorrecte. Le prisme fait la même chose. Je ne sais pas comment résoudre le problème. N'y a-t-il pas un moyen de dire au contrôle de "rafraîchir" son style? – Alex

+0

Pouvez-vous lier le style au modèle parent? Je ne peux pas me souvenir de la syntaxe du haut de ma tête ... –

+0

@Alex Si vous pouvez reproduire le problème sans utiliser Prism alors Prism n'est pas vraiment lié à la question. Pourriez-vous réviser la question pour supprimer des détails sans rapport et ajouter un exemple de code? –

0

Je voudrais juste itérer les contrôles enfants et attribuer le thème à chacun d'entre eux explicitement.

+0

Et comment exactement "attribuez-vous le thème"? Les thèmes résident dans le dictionnaire de ressources au niveau de l'application. Vous voulez définir explicitement la propriété de style à la ressource ayant la clé de style par défaut? – Alex

5

Le problème est que le ItemsControl de la région est stylé mais que ses enfants ne le font pas lorsque la région est utilisée dans un MenuItem. J'ai trouvé une solution en utilisant des menus dynamiques à partir de diverses sources:

WPF Sample Series – Databound HierarchicalDataTemplate Menu Sample

Building a Databound WPF Menu Using a HierarchicalDataTemplate

J'ai créé un IMenuService et MenuItemViewModel dans mon projet d'infrastructure, mettre en œuvre le IMenuService dans mon projet de Shell, et utiliser IMenuService dans mon module pour ajouter un menu.

public interface IMenuService 
{ 
    List<MenuItemViewModel> Menu { get; set; } 
    MenuItemViewModel FileMenu { get; set; } 
} 

public class MenuItemViewModel : NotificationObject 
{ 
    private string _header; 
    private bool _isEnabled = true; 
    private ICommand _command; 
    private Image _icon; 
    private string _inputGestureText; 
    private ObservableCollection<MenuItemViewModel> _children; 

    public MenuItemViewModel() 
    { 
     Children = new ObservableCollection<MenuItemViewModel>(); 
    } 

    public MenuItemViewModel(bool isSeparator) : this() 
    { 
     _isSeparator = isSeparator; 
    } 

    public string Header 
    { 
     get { return _header; } 
     set 
     { 
      _header = value; 
      RaisePropertyChanged("Header"); 
     } 
    } 

    public bool IsEnabled 
    { 
     get { return _isEnabled; } 
     set 
     { 
      _isEnabled = value; 
      RaisePropertyChanged("IsEnabled"); 
     } 
    } 

    public ICommand Command 
    { 
     get { return _command; } 
     set 
     { 
      _command = value; 
      RaisePropertyChanged("Command"); 
     } 
    } 

    public Image Icon 
    { 
     get { return _icon; } 
     set 
     { 
      _icon = value; 
      RaisePropertyChanged("Icon"); 
     } 
    } 

    public string InputGestureText 
    { 
     get { return _inputGestureText; } 
     set 
     { 
      _inputGestureText = value; 
      RaisePropertyChanged("InputGestureText"); 
     } 
    } 

    public ObservableCollection<MenuItemViewModel> Children 
    { 
     get { return _children; } 
     set { _children = value; } 
    } 

    private bool _isSeparator; 
    public bool IsSeparator 
    { 
     get { return _isSeparator; } 
     set { _isSeparator = value; } 
    } 
} 

MenuService dans le projet Shell:

[Export(typeof(IMenuService))] 
public class MenuService : IMenuService 
{ 
    [ImportingConstructor] 
    public MenuService() 
    { 
     _menu = new List<MenuItemViewModel>(); 
     _fileMenu = new MenuItemViewModel {Header = "_File"}; 
     _fileMenu.Children.Add(new MenuItemViewModel { Header = "_New" }); 
     _fileMenu.Children.Add(new MenuItemViewModel(true)); // Separator 

     _menu.Add(_fileMenu); 
    } 

    private static Image CreateImage(string url) 
    { 
     var image = new Image 
         { 
          Source = new BitmapImage(new Uri("Resources/" + url, UriKind.Relative)), 
          Height = 16, 
          Width = 16 
         }; 
     RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.NearestNeighbor); 
     return image; 
    } 

    private List<MenuItemViewModel> _menu; 
    public List<MenuItemViewModel> Menu 
    { 
     get { return _menu; } 
     set { _menu = value; } 
    } 

    private MenuItemViewModel _fileMenu; 
    public MenuItemViewModel FileMenu 
    { 
     get { return _fileMenu; } 
     set { _fileMenu = value; } 
    } 
} 

Dans Shell.xaml

<Window.Resources> 
    <Style TargetType="{x:Type MenuItem}" x:Key="separatorStyle"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type MenuItem}"> 
        <Separator HorizontalAlignment="Stretch" IsEnabled="False"/> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

    <Style BasedOn="{StaticResource {x:Type MenuItem}}" TargetType="{x:Type MenuItem}"> 
     <Setter Property="Command" Value="{Binding Command}"/> 
     <Setter Property="Icon" Value="{Binding Icon}"/> 
     <Setter Property="InputGestureText" Value="{Binding InputGestureText}"/> 
     <Setter Property="IsEnabled" Value="{Binding IsEnabled}"/> 
    </Style> 

    <HierarchicalDataTemplate DataType="{x:Type infrastructure:MenuItemViewModel}" ItemsSource="{Binding Path=Children, UpdateSourceTrigger=PropertyChanged}"> 
     <ContentPresenter Content="{Binding Header}" RecognizesAccessKey="True" /> 
    </HierarchicalDataTemplate> 

    <local:SeparatorStyleSelector x:Key="separatorStyleSelector"/> 

Dans le ShellViewModel:

[ImportingConstructor] 
    public ShellViewModel(IMenuService menuService) 
    { 
     Menu = menuService.Menu.ToObservableCollection(); 
    } 

    private ObservableCollection<MenuItemViewModel> _menu = new ObservableCollection<MenuItemViewModel>(); 
    public ObservableCollection<MenuItemViewModel> Menu 
    { 
     get { return _menu; } 
     set 
     { 
      _menu = value; 
      RaisePropertyChanged("MenuItems"); 
     } 
    } 

Ajout d'un menu à partir du module:

[ModuleExport(typeof(OptionModule))] 
public class OptionModule : IModule 
{ 
    [ImportingConstructor] 
    public OptionModule(IMenuService menuService) 
    { 
     menuService.ToolsMenu.Children.Add(new MenuItemViewModel {Header = "Options", Command = OptionCommand}); 
    } 
} 

Voici le SeparatorStyleSelector à partir du site de Karl ci-dessus:

public override Style SelectStyle(object item, DependencyObject container) 
    { 
     if (((MenuItemViewModel)item).IsSeparator) 
     { 
      return (Style) ((FrameworkElement) container).FindResource("separatorStyle"); 
     } 
     return base.SelectStyle(item, container); 
    } 
enter code here 
+0

Ceci est un bon exemple - le cas ci-dessus fonctionne bien pour les commandes régulières. Comment je peux toujours lier une commande dans le style à un chemin de liaison tel que {Binding Path = ActiveDocument.CloseCommand}? Y a-t-il un bon moyen de le faire? –