WPF实现类似网易云音乐的菜单切换

这里是借助三方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.xamlControls\HamburgerMenu里的文件。

项目地址:GitHub - MahApps/MahApps.Metro: A framework that allows developers to cobble together a better UI for their own WPF applications with minimal effort.

最终效果

示例代码

相关推荐
测试涛叔4 小时前
车载中控系统的UI自动化测试实践
ui
tealcwu4 小时前
【Unity基础】Unity中的UI系统
ui·unity·lucene
Liquid UI7 小时前
Amcor 如何借助 Liquid UI 实现SAP PM可靠性
ui·自动化·sap·制造
cl°8 小时前
【WPF】如何使用异步方法
经验分享·c#·wpf
镰刀出海9 小时前
如何使用Photoshop修改图标为纯色
ui·工具·photoshop·ps·图标
月落.9 小时前
WPF的行为(Behavior)
wpf
cl°13 小时前
WPF中视觉树和逻辑树的区别和联系
经验分享·学习·c#·wpf
tealcwu14 小时前
【Unity基础】初识UI Toolkit - 运行时UI
ui·unity·编辑器·游戏引擎
xu_duo_i16 小时前
Vxe UI 表格行编辑(默认不显示编辑框,点击后可编辑)
前端·vue.js·ui·vxe
不秃头的UI设计师18 小时前
跨越地域限制:在线原型设计软件的自由与便捷
ui·原型设计·原型设计软件·在线设计