这几天在做一个工具栏,用到了Menu控件,我们都知道它是条目控件,可以绑定数据源。自带的样式不太好看,于是自己就想修改一下,让它默认只有一个子项处于选中状态,再次打开会记录当前选中的是那个MenuItem.思路就是嵌入一个RadioButton控件并让其不可见,控制它的IsChecked属性与MenuItem的IsChecked属性之间的关系,支持添加Icon。
- Xaml及样式
<Window x:Class="WpfApp1Blend.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1Blend"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<Window.Resources>
<SolidColorBrush x:Key="Window.ToolBar.Selected.FgColor" Color="#42a4ff"></SolidColorBrush>
<SolidColorBrush x:Key="Window.ToolBar.Selected.BgColor" Color="#0E2E58"></SolidColorBrush>
<SolidColorBrush x:Key="Window.ToolBar.MouseOver.BgColor" Color="#0a2243"></SolidColorBrush>
<SolidColorBrush x:Key="Window.ToolBar.BorderBrushColor" Color="#0d3256"></SolidColorBrush>
<SolidColorBrush x:Key="Window.ToolBar.BgColor" Color="#031527"></SolidColorBrush>
<SolidColorBrush x:Key="Control.Static.FgColor" Color="#A5C0E2"></SolidColorBrush>
<Style x:Key="TextBlock.Static13" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Control.Static.FgColor}" />
<Setter Property="FontFamily" Value="Microsoft YaHei"></Setter>
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Margin" Value="5"></Setter>
<Setter Property="FontSize" Value="13" />
</Style>
<Style TargetType="{x:Type Menu}">
<Setter Property="Background" Value="{StaticResource Window.ToolBar.BgColor}"></Setter>
</Style>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="IsCheckable" Value="True"></Setter>
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
<Setter Property="VerticalAlignment" Value="Center"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border x:Name="Border_Ground" Background="Transparent">
<StackPanel>
<Grid Margin="10,3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<RadioButton x:Name="rdo" IsChecked="{Binding IsChecked,RelativeSource={RelativeSource Mode=TemplatedParent},Mode=OneWay}" GroupName="A" IsThreeState="False" VerticalAlignment="Center" ></RadioButton>
<Image Grid.Column="1" Source="{Binding Icon,RelativeSource={RelativeSource Mode=TemplatedParent}}" Stretch="None" Margin="0,0,0,0"/>
<TextBlock x:Name="tb" Grid.Column="2" Text="{TemplateBinding Header}" Style="{StaticResource TextBlock.Static13}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<Popup x:Name="popup" AllowsTransparency="True" PopupAnimation="Fade" StaysOpen="False" VerticalOffset="5" IsOpen="{TemplateBinding IsChecked}" AutomationProperties.HelpText="121212">
<Border Background="{StaticResource Window.ToolBar.BgColor}">
<ItemsPresenter></ItemsPresenter>
</Border>
</Popup>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" SourceName="rdo" Value="true">
<Setter TargetName="Border_Ground" Property="Background" Value="{DynamicResource Window.ToolBar.Selected.BgColor}"/>
<Setter TargetName="tb" Property="Foreground" Value="{DynamicResource Window.ToolBar.Selected.FgColor}"/>
<Setter Property="IsChecked" Value="True"></Setter>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="tb" Property="Foreground" Value="{DynamicResource Window.ToolBar.Selected.FgColor}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border_Ground" Property="Background" Value="{DynamicResource Window.ToolBar.MouseOver.BgColor}"/>
<Setter TargetName="Border_Ground" Property="BorderBrush" Value="{DynamicResource Window.ToolBar.BorderBrushColor}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Width="400" Height="400">
<StackPanel>
<Menu>
<MenuItem Header="A">
<MenuItem Header="A-1"/>
<MenuItem Header="A-2"/>
</MenuItem>
<MenuItem Header="B">
<MenuItem Header="B-1"></MenuItem>
<MenuItem Header="B-2"></MenuItem>
<MenuItem Header="B-3"></MenuItem>
<MenuItem Header="B-4"></MenuItem>
</MenuItem>
</Menu>
</StackPanel>
</Grid>
</Window>
- 效果
不足之处就是弹出popup面板之后,需要点击外部两次才能隐藏popup,我想第一点击是radiobutton失去焦点,再次点击是为了隐藏popup控件。有兴趣的同学可以自己再优化一下。