Menu as prism regions + themes problem
I am using a Menu control as a region. It works fine, however when I add a theme to my application (Added a resource-dictionary to my App.xaml) normal menus have the theme, but the views inside my region (which are menu-items) don't 开发者_运维百科have this theme.
What might be the reason behind it? Anybody has an idea for a work-around?
Alex.
The problem is that the ItemsControl of the region gets styled but its children do not when the region is used inside a MenuItem. I found a workaround by using dynamic menus from various sources:
WPF Sample Series – Databound HierarchicalDataTemplate Menu Sample
Building a Databound WPF Menu Using a HierarchicalDataTemplate
I created an IMenuService and MenuItemViewModel in my Infrastructure project, implement the IMenuService in my Shell project, and use IMenuService in my module to add a 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 in Shell project:
[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; }
}
}
In 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"/>
In the 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");
}
}
Adding a menu from the module:
[ModuleExport(typeof(OptionModule))]
public class OptionModule : IModule
{
[ImportingConstructor]
public OptionModule(IMenuService menuService)
{
menuService.ToolsMenu.Children.Add(new MenuItemViewModel {Header = "Options", Command = OptionCommand});
}
}
Here is the SeparatorStyleSelector from Karl's site above:
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
It could be a bug in the Prism Menu region adapter. I'd suggest reporting the issue on CodePlex.
I would just iterate the children controls and assign the theme to each of them explicitly.
精彩评论