WPF 制作侧边菜单 SideMenu

前面我们看了SideMenuItem,今天就在此基础上做出完整的侧边栏菜单喽。

支持多开和单开,具体效果看看视频吧。

看看效果吧:

image

 

下面就看看代码喽:

先添加一个SideMenu控件类:

using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;

namespace WPFDemos
{
    public class SideMenu : Control
    {
        public ObservableCollection<SideMenuItemViewModel> MenuItems
        {
            get { return (ObservableCollection<SideMenuItemViewModel>)GetValue(MenuItemsProperty); }
            set { SetValue(MenuItemsProperty, value); }
        }
        public static readonly DependencyProperty MenuItemsProperty =
            DependencyProperty.Register("MenuItems", typeof(ObservableCollection<SideMenuItemViewModel>), typeof(SideMenu), new PropertyMetadata(default(ObservableCollection<SideMenuItemViewModel>)));
        public static readonly RoutedEvent MenuItemselectedChangedEvent = EventManager.RegisterRoutedEvent("MenuItemselectedChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SideMenu));

        public event RoutedEventHandler MenuItemselectedChanged
        {
            add { AddHandler(MenuItemselectedChangedEvent, value); }
            remove { RemoveHandler(MenuItemselectedChangedEvent, value); }
        }
        public void OnMenuItemselectedChanged(DependencyObject dependencyObject)
        {
            RoutedEventArgs args = new RoutedEventArgs()
            {
                RoutedEvent = MenuItemselectedChangedEvent,
                Source = dependencyObject,
            };
            RaiseEvent(args);
        }
    }
}

这个类就很简单了,只是定义了选中事件和menuitem的列表集合。

再添加样式:

<Style x:Key="MenuItemstyle1" TargetType="ListBoxItem">
        <Setter Property="SnapsToDevicePixels" Value="true"/>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Setter Property="Margin" Value="0"/>
        <Setter Property="Padding" Value="0"/>
        <Setter Property="MinHeight" Value="40"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <local:SideMenuItem DataContext="{TemplateBinding DataContext}"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
</Style>
    <Style TargetType="local:SideMenu">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:SideMenu">
                    <Border Margin="{TemplateBinding Padding}"
                            Width="{TemplateBinding Width}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}">
                        <ScrollViewer Padding="0 0 -8 0">
                            <ListBox
                                 Focusable="False"
                                 Style="{StaticResource ListBoxStyle1}"
                                 ItemsSource="{Binding MenuItems,RelativeSource={RelativeSource TemplatedParent}}"
                                 ItemContainerStyle="{StaticResource MenuItemstyle1}"/>
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
</Style>

然后定义SideMenuViewModel:

using System.Collections.ObjectModel;

namespace WPFDemos
{
    public class SideMenuViewModel : BaseViewModel
    {
        private ObservableCollection<SideMenuItemViewModel> _menuItemViewModels;

        public ObservableCollection<SideMenuItemViewModel> MenuItemViewModels
        {
            get { return _menuItemViewModels; }
            set
            {
                _menuItemViewModels = value;
                OnPropertyChanged(nameof(MenuItemViewModels));
            }
        }
        private bool _supportMultiOpen;

        public bool SupportMultiOpen
        {
            get { return _supportMultiOpen; }
            set
            {
                _supportMultiOpen = value;
                OnPropertyChanged(nameof(SupportMultiOpen));
            }
        }

    }
}

最后改一下MainWindow:

<Window x:Class="WPFDemos.MainWindow"
        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:WPFDemos"
        mc:Ignorable="d"
        x:Name="widnow"
        WindowStartupLocation="CenterScreen"
        UseLayoutRounding="True"
        Background="LightBlue"
        Title="下拉菜单控件" Height="600" Width="1000">
    <Grid Background="LightBlue">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <local:SideMenu MenuItems="{Binding Models.MenuItemViewModels}" 
                        Background="#16181d"
                        HorizontalAlignment="Left"
                        MenuItemselectedChanged="S"
                        />
        <StackPanel Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock Text="刚刚点击了" FontSize="30" Margin="10"/>
            <TextBlock x:Name="log" HorizontalAlignment="Center" FontSize="30" VerticalAlignment="Bottom" Margin="0 0 0 50"/>
        </StackPanel>
    </Grid>
</Window>

窗口后台代码定义列表的DataContext:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WPFDemos
{
    public partial class MainWindow : Window
    {
        public SideMenuViewModel Models { get; set; }
        public MainWindow()
        {
            Models = new SideMenuViewModel() { SupportMultiOpen = true };
            Models.MenuItemViewModels = new ObservableCollection<SideMenuItemViewModel>
            {
                new SideMenuItemViewModel()
                {   
                    Parent = Models,
                    HeaderText = "快速开始",
                    IconGeometry = FindResource("Flag") as Geometry,
                    Items = new List<object>()
                    {
                        "5.0新变化",
                        "第一个项目",
                        "第一个模块",
                        "自定义用户",
                        "捐赠",
                        "FAQ"
                    },
                },
                new SideMenuItemViewModel()
                {   
                    Parent = Models,
                    HeaderText = "框架配置",
                    IconGeometry = FindResource("IconInfo") as Geometry,
                    Items = new List<object>()
                    {
                        "Test1",
                        "Test2",
                        "Test3",
                        "Test5",
                    },
                },
                new SideMenuItemViewModel()
                {
                    Parent = Models,
                    HeaderText = "模型层",
                    IconGeometry = FindResource("IconInfo") as Geometry,
                    Items = new List<object>()
                    {
                        "Test1",
                        "Test2",
                        "Test3",
                        "Test5",
                    },
                },
                new SideMenuItemViewModel()
                {
                    Parent = Models,
                    HeaderText = "视图模型层",
                    IconGeometry = FindResource("IconInfo") as Geometry,
                    Items = new List<object>()
                    {
                        "Test1",
                        "Test2",
                        "Test3",
                        "Test5",
                    },
                },
                new SideMenuItemViewModel()
                {
                    Parent = Models,
                    HeaderText = "控制器层",
                    IconGeometry = FindResource("IconInfo") as Geometry,
                    Items = new List<object>()
                    {
                        "Test1",
                        "Test2",
                        "Test3",
                        "Test5",
                    },
                },
            };

            InitializeComponent();
            DataContext = this;
        }
        private void S(object sender, RoutedEventArgs e)
        {
            var s = e.OriginalSource as ListBox;
            var str = s.SelectedItem;
            log.Text = str.ToString();
        }
    }
}

这就完成 啦。

注意:本次是在昨天的基础上做的修改,详情见公众号历史记录喽~

需要源码的小伙伴,关注公众号WPF UI,回复SideMenu即可获取哦

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情

    暂无评论内容