这里是借助三方UI框架实现了,感兴趣的小伙伴可以看一下。
深色模式:
浅色模式:
这里主要使用了以下三个包:
MahApps.Metro:UI库,提供菜单导航和其它控件
实现步骤:1、使用BlurWindow放置一个窗口
1 <tianxia:BlurWindow x:Class="GameOptimizerTool.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 9 xmlns:tianxia="clr-namespace:TianXiaTech" 10 mc:Ignorable="d" 11 Title="工具箱" Height="650" Width="1100" TitleForeground="{DynamicResource MahApps.Brushes.Text}" Icon="logo.png" Background="{DynamicResource MahApps.Brushes.ThemeBackground}"> 12 <Grid> 13 </Grid> 14 </tianxia:BlurWindow>
这里的一些颜色使用了动态资源 ,以便实现深色和浅色模式的切换。
2、引入 XAML命名空间前缀
1 xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" 2 xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" 3 xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
3、放置HamburgerMenu控件
通过设置HamburgerMenu.ItemsSource属性,可以设置菜单项
通过设置HamburgerMenu.OptionsItemsSource属性,可以增加设置项,设置项会显示在左下角
注意:这里我们需要设置控件的控件模板,否则 会显示异常
1 <mah:HamburgerMenu x:Name="HamburgerMenuControl" 2 CompactPaneLength="48" 3 OpenPaneLength="70" 4 HamburgerWidth="48" 5 IsPaneOpen="True" 6 ItemInvoked="HamburgerMenuControl_OnItemInvoked" 7 ItemTemplate="{StaticResource MenuItemTemplate}" 8 OptionsItemTemplate="{StaticResource MenuItemTemplate}" 9 SelectedIndex="0" 10 Style="{StaticResource MahApps.Styles.HamburgerMenu.Ripple}" 11 VerticalScrollBarOnLeftSide="False"> 12 <!--Items--> 13 <mah:HamburgerMenu.ItemsSource> 14 <mah:HamburgerMenuItemCollection> 15 <mah:HamburgerMenuIconItem Icon="{iconPacks:Material Kind=Home}" Label="首页"> 16 <mah:HamburgerMenuIconItem.Tag> 17 <local:HomeView /> 18 </mah:HamburgerMenuIconItem.Tag> 19 </mah:HamburgerMenuItemCollection> 20 </mah:HamburgerMenu.ItemsSource> 21 22 <!--设置--> 23 <mah:HamburgerMenu.OptionsItemsSource> 24 <mah:HamburgerMenuItemCollection> 25 <mah:HamburgerMenuIconItem Icon="{iconPacks:Material Kind=Cog}" Label="设置"> 26 <mah:HamburgerMenuIconItem.Tag> 27 <local:OptimizerView /> 28 </mah:HamburgerMenuIconItem.Tag> 29 </mah:HamburgerMenuIconItem> 30 </mah:HamburgerMenuItemCollection> 31 </mah:HamburgerMenu.OptionsItemsSource> 32 33 <mah:HamburgerMenu.ContentTemplate> 34 <DataTemplate DataType="{x:Type mah:HamburgerMenuIconItem}"> 35 <Grid Margin="20 0 10 0"> 36 <Grid.RowDefinitions> 37 <RowDefinition Height="Auto" /> 38 <RowDefinition Height="*" /> 39 </Grid.RowDefinitions> 40 <!--标题文本,如果需要大标题显示,取消注释这段代码--> 41 <TextBlock Grid.Row="0" 42 Margin="0 15 0 5" 43 Padding="0" 44 FontFamily="{DynamicResource MahApps.Fonts.Family.Header}" 45 FontSize="{DynamicResource MahApps.Font.Size.Header}" 46 Foreground="{DynamicResource MahApps.Brushes.Text}" 47 Text="{Binding Label}" /> 48 <ScrollViewer Grid.Row="1" 49 Focusable="False" 50 HorizontalScrollBarVisibility="Disabled" 51 VerticalScrollBarVisibility="Auto"> 52 <ContentControl Content="{Binding Tag}" Focusable="False" /> 53 </ScrollViewer> 54 </Grid> 55 </DataTemplate> 56 </mah:HamburgerMenu.ContentTemplate> 57 58 </mah:HamburgerMenu>
4、设置HamburgerMenu控件菜单项的样式
我们直接放到窗口资源 里
1 <tianxia:BlurWindow.Resources> 2 <ResourceDictionary> 3 <!--左侧菜单的样式--> 4 <DataTemplate x:Key="MenuItemTemplate" DataType="{x:Type mah:HamburgerMenuIconItem}"> 5 <Grid Height="40"> 6 <Grid.ColumnDefinitions> 7 <ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type mah:HamburgerMenu}}, Path=CompactPaneLength}" /> 8 <ColumnDefinition /> 9 </Grid.ColumnDefinitions> 10 <ContentControl Grid.Column="0" 11 HorizontalAlignment="Center" 12 VerticalAlignment="Center" 13 Content="{Binding Icon}" 14 Focusable="False" 15 IsTabStop="False" /> 16 <TextBlock Grid.Column="1" 17 VerticalAlignment="Center" 18 FontSize="13" 19 Text="{Binding Label}" /> 20 </Grid> 21 </DataTemplate> 22 23 <ObjectDataProvider x:Key="DisplayModeEnumValues" 24 MethodName="GetValues" 25 ObjectType="{x:Type mah:SplitViewDisplayMode}"> 26 <ObjectDataProvider.MethodParameters> 27 <x:Type TypeName="mah:SplitViewDisplayMode" /> 28 </ObjectDataProvider.MethodParameters> 29 </ObjectDataProvider> 30 31 <ObjectDataProvider x:Key="VisibilityEnumValues" 32 MethodName="GetValues" 33 ObjectType="{x:Type Visibility}"> 34 <ObjectDataProvider.MethodParameters> 35 <x:Type TypeName="Visibility" /> 36 </ObjectDataProvider.MethodParameters> 37 </ObjectDataProvider> 38 39 <Style x:Key="MahApps.Styles.ListBoxItem.HamburgerMenuItem.Ripple" 40 BasedOn="{StaticResource MahApps.Styles.ListBoxItem.HamburgerMenuItem}" 41 TargetType="{x:Type ListBoxItem}"> 42 <Setter Property="Template"> 43 <Setter.Value> 44 <ControlTemplate TargetType="{x:Type ListBoxItem}"> 45 <Grid x:Name="RootGrid" 46 Background="Transparent" 47 RenderOptions.ClearTypeHint="{TemplateBinding RenderOptions.ClearTypeHint}"> 48 <Border x:Name="Border" 49 Background="{TemplateBinding Background}" 50 BorderBrush="{TemplateBinding BorderBrush}" 51 BorderThickness="{TemplateBinding BorderThickness}" 52 SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 53 <Grid Margin="{TemplateBinding BorderThickness}"> 54 <Grid HorizontalAlignment="Left" 55 VerticalAlignment="Center" 56 Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type mah:HamburgerMenu}}, Path=ShowSelectionIndicator, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"> 57 <Rectangle x:Name="SelectionIndicator" 58 Width="{DynamicResource HamburgerMenuSelectionIndicatorThemeWidth}" 59 Height="{DynamicResource HamburgerMenuSelectionIndicatorThemeHeight}" 60 Fill="{TemplateBinding Foreground}" 61 Focusable="False" 62 Opacity="0.0" /> 63 </Grid> 64 <materialDesign:Ripple x:Name="ContentPresenter" 65 Padding="{TemplateBinding Padding}" 66 HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 67 VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" 68 Content="{TemplateBinding Content}" 69 ContentTemplate="{TemplateBinding ContentTemplate}" 70 ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" 71 Feedback="{DynamicResource MahApps.Brushes.Gray.MouseOver}" 72 Focusable="False" 73 SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 74 </Grid> 75 </Grid> 76 <ControlTemplate.Triggers> 77 <Trigger Property="IsSelected" Value="True"> 78 <Setter TargetName="Border" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.SelectedBackgroundBrush), Mode=OneWay}" /> 79 <Setter TargetName="ContentPresenter" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.SelectedForegroundBrush), Mode=OneWay}" /> 80 <Setter TargetName="SelectionIndicator" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.SelectedForegroundBrush), Mode=OneWay}" /> 81 <Setter TargetName="SelectionIndicator" Property="Opacity" Value="1.0" /> 82 </Trigger> 83 <MultiTrigger> 84 <MultiTrigger.Conditions> 85 <Condition Property="IsSelected" Value="True" /> 86 <Condition Property="Selector.IsSelectionActive" Value="True" /> 87 </MultiTrigger.Conditions> 88 <Setter TargetName="Border" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.ActiveSelectionBackgroundBrush), Mode=OneWay}" /> 89 <Setter TargetName="ContentPresenter" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.ActiveSelectionForegroundBrush), Mode=OneWay}" /> 90 <Setter TargetName="SelectionIndicator" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.ActiveSelectionForegroundBrush), Mode=OneWay}" /> 91 </MultiTrigger> 92 93 <MultiTrigger> 94 <MultiTrigger.Conditions> 95 <Condition Property="IsMouseOver" Value="True" /> 96 <Condition Property="IsSelected" Value="True" /> 97 </MultiTrigger.Conditions> 98 <Setter TargetName="Border" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.HoverSelectedBackgroundBrush), Mode=OneWay}" /> 99 <Setter TargetName="ContentPresenter" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.HoverSelectedForegroundBrush), Mode=OneWay}" /> 100 <Setter TargetName="SelectionIndicator" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.HoverSelectedForegroundBrush), Mode=OneWay}" /> 101 </MultiTrigger> 102 <MultiTrigger> 103 <MultiTrigger.Conditions> 104 <Condition Property="IsMouseOver" Value="True" /> 105 <Condition Property="IsSelected" Value="False" /> 106 </MultiTrigger.Conditions> 107 <Setter TargetName="Border" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.HoverBackgroundBrush), Mode=OneWay}" /> 108 <Setter TargetName="ContentPresenter" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.HoverForegroundBrush), Mode=OneWay}" /> 109 <Setter TargetName="SelectionIndicator" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.HoverForegroundBrush), Mode=OneWay}" /> 110 </MultiTrigger> 111 112 <Trigger Property="mah:ItemHelper.IsMouseLeftButtonPressed" Value="True"> 113 <Setter TargetName="Border" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.MouseLeftButtonPressedBackgroundBrush), Mode=OneWay}" /> 114 <Setter TargetName="ContentPresenter" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.MouseLeftButtonPressedForegroundBrush), Mode=OneWay}" /> 115 <Setter TargetName="SelectionIndicator" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.MouseLeftButtonPressedForegroundBrush), Mode=OneWay}" /> 116 </Trigger> 117 <Trigger Property="mah:ItemHelper.IsMouseRightButtonPressed" Value="True"> 118 <Setter TargetName="Border" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.MouseRightButtonPressedBackgroundBrush), Mode=OneWay}" /> 119 <Setter TargetName="ContentPresenter" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.MouseRightButtonPressedForegroundBrush), Mode=OneWay}" /> 120 <Setter TargetName="SelectionIndicator" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.MouseRightButtonPressedForegroundBrush), Mode=OneWay}" /> 121 </Trigger> 122 123 <Trigger Property="IsEnabled" Value="False"> 124 <Setter TargetName="Border" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.DisabledBackgroundBrush), Mode=OneWay}" /> 125 <Setter TargetName="ContentPresenter" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.DisabledForegroundBrush), Mode=OneWay}" /> 126 <Setter TargetName="RootGrid" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background, Mode=OneWay}" /> 127 <Setter TargetName="SelectionIndicator" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.DisabledForegroundBrush), Mode=OneWay}" /> 128 </Trigger> 129 <MultiTrigger> 130 <MultiTrigger.Conditions> 131 <Condition Property="IsEnabled" Value="False" /> 132 <Condition Property="IsSelected" Value="True" /> 133 </MultiTrigger.Conditions> 134 <Setter TargetName="Border" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.DisabledSelectedBackgroundBrush), Mode=OneWay}" /> 135 <Setter TargetName="ContentPresenter" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.DisabledSelectedForegroundBrush), Mode=OneWay}" /> 136 <Setter TargetName="SelectionIndicator" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(mah:ItemHelper.DisabledSelectedForegroundBrush), Mode=OneWay}" /> 137 </MultiTrigger> 138 </ControlTemplate.Triggers> 139 </ControlTemplate> 140 </Setter.Value> 141 </Setter> 142 <Setter Property="mah:ItemHelper.ActiveSelectionBackgroundBrush" Value="Transparent" /> 143 <Setter Property="mah:ItemHelper.ActiveSelectionForegroundBrush" Value="{DynamicResource MahApps.Brushes.AccentBase}" /> 144 <Setter Property="mah:ItemHelper.DisabledForegroundBrush" Value="{DynamicResource MahApps.Brushes.Gray}" /> 145 <Setter Property="mah:ItemHelper.DisabledSelectedBackgroundBrush" Value="Transparent" /> 146 <Setter Property="mah:ItemHelper.DisabledSelectedForegroundBrush" Value="{DynamicResource MahApps.Brushes.Gray}" /> 147 <Setter Property="mah:ItemHelper.HoverBackgroundBrush" Value="{DynamicResource MahApps.Brushes.Gray.SemiTransparent}" /> 148 <Setter Property="mah:ItemHelper.HoverSelectedBackgroundBrush" Value="{DynamicResource MahApps.Brushes.Gray.SemiTransparent}" /> 149 <Setter Property="mah:ItemHelper.HoverSelectedForegroundBrush" Value="{DynamicResource MahApps.Brushes.AccentBase}" /> 150 <Setter Property="mah:ItemHelper.SelectedBackgroundBrush" Value="Transparent" /> 151 <Setter Property="mah:ItemHelper.SelectedForegroundBrush" Value="{DynamicResource MahApps.Brushes.AccentBase}" /> 152 </Style> 153 154 <Style x:Key="MahApps.Styles.HamburgerMenu.Ripple" 155 BasedOn="{StaticResource MahApps.Styles.HamburgerMenu}" 156 TargetType="{x:Type mah:HamburgerMenu}"> 157 <Setter Property="ItemContainerStyle" Value="{StaticResource MahApps.Styles.ListBoxItem.HamburgerMenuItem.Ripple}" /> 158 <Setter Property="OptionsItemContainerStyle" Value="{StaticResource MahApps.Styles.ListBoxItem.HamburgerMenuItem.Ripple}" /> 159 <Setter Property="PaneBackground" Value="{DynamicResource MahApps.Brushes.ThemeBackground}" /> 160 <Setter Property="PaneForeground" Value="{DynamicResource MahApps.Brushes.Text}" /> 161 <Setter Property="ShowSelectionIndicator" Value="True" /> 162 </Style> 163 164 </ResourceDictionary> 165 </tianxia:BlurWindow.Resources>
5、增加菜单项切换时的事件处理程序
在放置HamburgerMenu控件时,设置了ItemInvoked事件
1 ItemInvoked="HamburgerMenuControl_OnItemInvoked"
事件处理程序如下:
1 private void HamburgerMenuControl_OnItemInvoked(object sender, MahApps.Metro.Controls.HamburgerMenuItemInvokedEventArgs args) 2 { 3 HamburgerMenuControl.Content = args.InvokedItem; 4 }
6、切换深色模式
MahApps.Metro提供了模式切换的功能,直接调用以下代码即可
1 private void Window_Loaded(object sender, RoutedEventArgs e) 2 { 3 ThemeManager.Current.ChangeThemeBaseColor(Application.Current, "Dark"); 4 }
HamburgerMenu控件是如何实现的
这里内部其实是使用的ListBox,ListBox自身已经具备了切换事件和选中事件,所以在ListBox的基础上,加以封装,就能实现HamburgerMenu。
这里不做详细介绍,可以参考MahApps.Metro源码里的Themes\HamburgerMenuTemplate.xaml和Controls\HamburgerMenu里的文件。
项目地址:GitHub - MahApps/MahApps.Metro: A framework that allows developers to cobble together a better UI for their own WPF applications with minimal effort.
最终效果
示例代码