菜单作为棱镜区域 + 主题问题 [英] Menu as prism regions + themes problem
问题描述
我使用 Menu 控件作为区域.它工作正常,但是当我向我的应用程序添加一个主题时(向我的 App.xaml 添加了一个资源字典)普通菜单有这个主题,但是我区域内的视图(菜单项)没有这个主题.
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?
亚历克斯.
推荐答案
问题在于,当在 MenuItem 中使用该区域时,该区域的 ItemsControl 会设置样式,但其子项不会设置样式.我通过使用来自各种来源的动态菜单找到了一种解决方法:
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 示例系列 – 数据绑定HierarchicalDataTemplate 菜单示例
使用 HierarchicalDataTemplate 构建数据绑定 WPF 菜单
我在基础结构项目中创建了 IMenuService 和 MenuItemViewModel,在我的 Shell 项目中实现了 IMenuService,并在我的模块中使用 IMenuService 添加菜单.
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; }
}
}
Shell 项目中的 MenuService:
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; }
}
}
在 Shell.xaml 中
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"/>
在 ShellViewModel 中:
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");
}
}
从模块添加菜单:
[ModuleExport(typeof(OptionModule))]
public class OptionModule : IModule
{
[ImportingConstructor]
public OptionModule(IMenuService menuService)
{
menuService.ToolsMenu.Children.Add(new MenuItemViewModel {Header = "Options", Command = OptionCommand});
}
}
这是来自上面 Karl 站点的 SeparatorStyleSelector:
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屋!