Menu:菜单控件应用实例

Menu : Windows 菜单控件,该控件可用于按层次组织与命令和事件处理程序关联的元素。

父类:MenuBase - ItemsControl

属性:IsMainMenu 菜单是否接收主菜单激活通知(Alt或F10键)

Menu中的菜单项:MenuItem --菜单中可选择的项

父类:HeaderedItemsControl

MenuItem的属性:HeaderedItemsControl

Icon 项图标

InputGestureText 设置描述输入的笔势(快捷键)

Command 与菜单项关联的命令

Header 菜单项文本

IsChecked 项是否选中

IsSubmenuOpen 子菜单是否处于打开

IsHighlighted 是否突出显示

事件:Click

实现效果

创建数据库及表及添加初始数据

打开数据库,记住自己的服务器名称;

输入下面代码创建数据库及表及添加初始数据

cs 复制代码
--判断数据库SqlData  是否存在,不存在则创建`
`IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = N'SqlData')`
`BEGIN`
    `CREATE DATABASE SqlData`
`END`

`--切换到SqlData数据库`
`USE SqlData`


`--DROP TABLE MenuInfos;`

`--创建表`
`CREATE TABLE MenuInfos (`
    `MenuId INT IDENTITY(1,1) PRIMARY KEY,`
    `MenuName NVARCHAR(100) NOT NULL,`
    `ParentId INT NULL,`
    `MKey NVARCHAR(100)  NULL,`
    
`);`

`--CONSTRAINT FK_ParentMenu FOREIGN KEY (ParentId) REFERENCES MenuItem(MenuId)`

`--添加数据`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('系统管理', 0,'Alt+S');`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('新增菜单', 1,NULL);`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('菜单列表', 1,'Ctrl+M');`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('角色列表', 1,NULL);`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('权限分配', 1,'Ctrl+R');`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('用户列表', 1,NULL);`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('新增用户', 1,NULL);`

`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('成绩管理', 0,'Alt+T');`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('成绩列表', 8,NULL);`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('成绩信息输入', 8,NULL);`

`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('学生信息管理', 0,'Alt+D');`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('新增学生', 14,NULL);`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('新增角色', 1,'Alt+Shift+S');`

`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('学生列表', 11,NULL);`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('班级管理', 0,'Alt+C');`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('年级管理', 0,'Alt+G');`

`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('班级列表', 15,NULL);`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('新增班级', 15,'Ctrl+Alt+C');`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('年级列表', 16,NULL);`

`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('新增年级', 16,NULL);`
`INSERT INTO MenuInfos (MenuName, ParentId, MKey) VALUES ('学生查询', 14,NULL);

创建完如下

创建WPF程序

cs 复制代码
<Window
    x:Class="MenuDemo.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:local="clr-namespace:MenuDemo"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="Menu案例"
    Width="500"
    Height="300"
    mc:Ignorable="d">
    <Grid>
        <Menu
            Name="menus"
            Width="500"
            Height="37"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Background="#FF0ABEFF" />
    </Grid>
</Window>

在App.config 添加连接数据库的资源字典

cs 复制代码
	<connectionStrings>
		<add name="connStr" connectionString="Server=DESKTOP-JRTKHSS\SQLEXPRESS;DataBase=SqlData;Uid=sa;Pwd=123456" />
	</connectionStrings>

添加文件夹dbhelper及工具类CommandInfo、SqlHelper

cs 复制代码
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Helper
{
    public class CommandInfo
    {
        public string CommandText;//sql或存储过程名
        public SqlParameter[] Paras; //参数列表
        public bool IsProc; //是否是存储过程
        public CommandInfo()
        {

        }

        public CommandInfo(string comText, bool isProc)
        {
            this.CommandText = comText;
            this.IsProc = isProc;
        }

        public CommandInfo(string sqlText, bool isProc, SqlParameter[] para)
        {
            this.CommandText = sqlText;
            this.Paras = para;
            this.IsProc = isProc;
        }
    }
}
cs 复制代码
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Helper
{
   public class SqlHelper
    {
        //1.连接字符串
        private static string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;

        //2.Command三个执行方法

        /// <summary>
        /// 增、删、改的通用方法
        /// 执行Sql语句或存储过程,返回受影响的行数
        /// </summary>
        /// <param name="sql">sql语句或存储过程名</param>
        /// <param name="cmdType">执行的脚本类型 1:sql语句  2:存储过程</param>
        /// <param name="parameters">参数列表</param>
        /// <returns></returns>
        public static int ExecuteNonQuery(string sql, int cmdType, params SqlParameter[] parameters)
        {
            //select @@Identity 返回上一次插入记录时自动产生的ID
            int result = 0;//返回结果
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                //执行脚本的对象cmd
                SqlCommand cmd = BuilderCommand(conn, sql, cmdType, null, parameters);
                result = cmd.ExecuteNonQuery();//执行T-SQL并返回受影响行数
                cmd.Parameters.Clear();
            }
            //using原理:类似于try finally
            return result;
        }

        /// <summary>
        /// 执行sql查询,返回第一行第一列的值
        /// </summary>
        /// <param name="sql">sql语句或存储过程</param>
        /// <param name="cmdType">执行的脚本类型 1:sql语句  2:存储过程</param>
        /// <param name="parameters">参数列表</param>
        /// <returns></returns>
        public static object ExecuteScalar(string sql, int cmdType, params SqlParameter[] parameters)
        {
            object result = null;//返回结果
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                //执行脚本的对象cmd
                SqlCommand cmd = BuilderCommand(conn, sql, cmdType, null, parameters);
                result = cmd.ExecuteScalar();//执行T-SQL并返回第一行第一列的值
                cmd.Parameters.Clear();
                if (result == null || result == DBNull.Value)
                {
                    return null;
                }
                else
                {
                    return result;
                }
            }
        }

        /// <summary>
        /// 执行sql查询,返回SqlDataReader对象
        /// </summary>
        /// <param name="sql">sql语句或存储过程</param>
        /// <param name="cmdType">执行的脚本类型 1:sql语句  2:存储过程</param>
        /// <param name="parameters">参数列表</param>
        /// <returns></returns>
        public static SqlDataReader ExecuteReader(string sql, int cmdType, params SqlParameter[] parameters)
        {
            SqlConnection conn = new SqlConnection(connStr);
            SqlCommand cmd = BuilderCommand(conn, sql, cmdType, null, parameters);
            SqlDataReader reader;
            try
            {
                reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                return reader;
            }
            catch (Exception ex)
            {
                conn.Close();
                throw new Exception("创建reader对象发生异常", ex);
            }
        }

        //SqlDataAdapter两种填充、Update方法(自动配置命令)
        /// <summary>
        /// 执行查询,查询结果填充到DataTable 只针对查询一个表的情况
        /// </summary>
        /// <param name="sql">sql语句或存储过程</param>
        /// <param name="cmdType">执行的脚本类型 1:sql语句  2:存储过程</param>
        /// <param name="parameters">参数列表</param>
        /// <returns></returns>
        public static DataTable GetDataTable(string sql, int cmdType, params SqlParameter[] parameters)
        {
            DataTable dt = null;
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                SqlCommand cmd = BuilderCommand(conn, sql, cmdType, null, parameters);
                SqlDataAdapter da = new SqlDataAdapter(cmd);
                dt = new DataTable();
                da.Fill(dt);
            }
            return dt;
        }

        /// <summary>
        /// 执行查询,数据填充到DataSet
        /// </summary>
        /// <param name="sql">sql语句或存储过程</param>
        /// <param name="cmdType">执行的脚本类型 1:sql语句  2:存储过程</param>
        /// <param name="parameters">参数列表</param>
        /// <returns></returns>
        public static DataSet GetDataSet(string sql, int cmdType, params SqlParameter[] parameters)
        {
            DataSet ds = null;
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                SqlCommand cmd = BuilderCommand(conn, sql, cmdType, null, parameters);
                //数据适配器
                //conn 自动打开  断开式连接
                SqlDataAdapter da = new SqlDataAdapter(cmd);
                ds = new DataSet();
                da.Fill(ds);
                //自动关闭conn
            }
            return ds;
        }

        /// <summary>
        /// SqlDataAdapter更新DataTable到数据库(不常用)
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="sql"></param>
        /// <returns></returns>
        public static bool UpdateDataTable(DataTable dt,string sql)
        {
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                SqlDataAdapter da = new SqlDataAdapter(sql, conn);
                SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da);
                int count= da.Update(dt);
                if (count > 0)
                    return true;
            }
            return false;
        }

        //执行事务的方法三个

        /// <summary>
        /// 事务 执行批量sql
        /// </summary>
        /// <param name="listSql"></param>
        /// <returns></returns>
        public static bool ExecuteTrans(List<string> listSql)
        {
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                conn.Open();
                SqlTransaction trans = conn.BeginTransaction();
                SqlCommand cmd = BuilderCommand(conn, "", 1, trans);
                try
                {
                    int count = 0;
                    for (int i = 0; i < listSql.Count; i++)
                    {
                        if (listSql[i].Length > 0)
                        {
                            cmd.CommandText = listSql[i];
                            cmd.CommandType = CommandType.Text;
                            count += cmd.ExecuteNonQuery();
                        }
                    }
                    trans.Commit();
                    return true;
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    throw new Exception("执行事务出现异常", ex);
                }
            }
        }

        /// <summary>
        /// 事务 批量执行 CommandInfo 包括sql,脚本类型,参数列表
        /// </summary>
        /// <param name="comList"></param>
        /// <returns></returns>
        public static bool ExecuteTrans(List<CommandInfo> comList)
        {
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                conn.Open();
                SqlTransaction trans = conn.BeginTransaction();
                SqlCommand cmd = BuilderCommand(conn, "", 1, trans);
                try
                {
                    int count = 0;
                    for (int i = 0; i < comList.Count; i++)
                    {
                        cmd.CommandText = comList[i].CommandText;
                        if (comList[i].IsProc)
                            cmd.CommandType = CommandType.StoredProcedure;
                        else
                            cmd.CommandType = CommandType.Text;

                        if (comList[i].Paras != null && comList[i].Paras.Length > 0)
                        {
                            cmd.Parameters.Clear();
                            foreach (var p in comList[i].Paras)
                            {
                                cmd.Parameters.Add(p);
                            }
                        }
                        count += cmd.ExecuteNonQuery();

                    }
                    trans.Commit();
                    return true;
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    throw new Exception("执行事务出现异常", ex);
                }
            }
        }

        public static T ExecuteTrans<T>(Func<IDbCommand, T> action)
        {
            using (IDbConnection conn = new SqlConnection(connStr))
            {
                conn.Open();
                IDbTransaction trans = conn.BeginTransaction();
                IDbCommand cmd = conn.CreateCommand();
                cmd.Transaction = trans;
                return action(cmd);
            }
        }

        //构造Command对象方法
        /// <summary>
        /// 构建SqlCommand
        /// </summary>
        /// <param name="conn">数据库连接对象</param>
        /// <param name="sql">SQL语句或存储过程</param>
        /// <param name="comType">命令字符串的类型</param>
        /// <param name="trans">事务</param>
        /// <param name="paras">参数数组</param>
        /// <returns></returns>
        private static SqlCommand BuilderCommand(SqlConnection conn, string sql, int cmdType, SqlTransaction trans, params SqlParameter[] paras)
        {
            if (conn == null) throw new ArgumentNullException("连接对象不能为空!");
            SqlCommand command = new SqlCommand(sql, conn);
            if (cmdType == 2)
                command.CommandType = CommandType.StoredProcedure;
            if (conn.State == ConnectionState.Closed)
                conn.Open();
            if (trans != null)
                command.Transaction = trans;
            if (paras != null && paras.Length > 0)
            {
                command.Parameters.Clear();
                command.Parameters.AddRange(paras);
            }
            return command;
        }

        /// <summary>
        /// 将参数数组添加到IDbCommand的参数集合中
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public static void AddParas(IDbCommand cmd, SqlParameter[] paras)
        {
            if (paras != null && paras.Length > 0)
            {
                foreach (var p in paras)
                {
                    cmd.Parameters.Add(p);
                }
            }
        }

        /// <summary>
        /// 初始化IDbCommand的操作(每步的执行)
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="sql"></param>
        /// <param name="cmdType"></param>
        /// <param name="paras"></param>
        public static void InitIdbCommand(IDbCommand cmd, string sql, int cmdType, SqlParameter[] paras)
        {
            cmd.CommandText = sql;
            if (cmdType == 1)
                cmd.CommandType = CommandType.Text;
            else
                cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Clear();
            AddParas(cmd, paras);
        }

        /// <summary>
        /// 执行Insert \Update\Delete语句
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="cmdType"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public static bool Execute(string sql, int cmdType, params SqlParameter[] paras)
        {
            int count = 0;
            count = ExecuteNonQuery(sql, cmdType, paras);
            if (count > 0)
                return true;
            return false;

        }

        /// <summary>
        /// 执行查询,返回指定类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <param name="cmdType"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public static T GetValByExecute<T>(string sql,int cmdType, params SqlParameter[] paras)
        {
            object oVal = null;
            oVal = ExecuteScalar(sql, cmdType, paras);
            if (oVal != null && oVal.ToString() != "")
                return (T)Convert.ChangeType(oVal, typeof(T));
            else
                return default(T);
        }

        /// <summary>
        /// Adapter提交DataTable  单表
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="sql"></param>
        /// <returns></returns>
        public static int AdapterUpdateDt(DataTable dt,string sql)
        {
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                SqlDataAdapter da = new SqlDataAdapter(sql, conn);
                SqlCommandBuilder sbuilder = new SqlCommandBuilder(da);
                return da.Update(dt);
            }
        }
    }
}

如果报错则按提示using

添加models文件夹及菜单列表类MenuInfo

cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ImSql.Models
{
    public class MenuInfo
    {
        public int MenuId { get; set; }
        public string MenuName { get; set; }
        public int ParentId { get; set; }
        public string MKey { get; set; }
    }
}

在页面中添加初始化事件:Loaded

在页面后台代码中添加如下代码

cs 复制代码
 //定义一个递归加载方法
 private void AddMenuItems(List<MenuInfo> allMenus, MenuItem pMenu, int parentId)
 {
     //获取当前的子菜单列表
     var subList = allMenus.Where(m => m.ParentId == parentId);
     foreach (var mi in subList)
     {
         MenuItem mItem = new MenuItem();
         mItem.Header = mi.MenuName;
         if (!string.IsNullOrEmpty(mi.MKey))
             mItem.InputGestureText = mi.MKey;
         if (pMenu != null)
             pMenu.Items.Add(mItem);//子菜单
         else
             menus.Items.Add(mItem);//一级菜单
         AddMenuItems(allMenus, mItem, mi.MenuId);
     }
 }

 private void Window_Loaded(object sender, RoutedEventArgs e)
 {
     List<MenuInfo> menuList = GetMenuList();
     //调用递归方法
     AddMenuItems(menuList, null, 0);

 }



 /// <summary>
 /// 获取菜单数据
 /// </summary>
 /// <returns></returns>
 private List<MenuInfo> GetMenuList()
 {
     string sql = "select MenuId,MenuName,ParentId,MKey from MenuInfos";
     SqlDataReader dr = SqlHelper.ExecuteReader(sql, 1);
     List<MenuInfo> list = new List<MenuInfo>();
     while (dr.Read())
     {
         MenuInfo menu = new MenuInfo();
         menu.MenuId = (int)dr["MenuId"];
         menu.MenuName = dr["MenuName"].ToString();
         menu.ParentId = (int)dr["ParentId"];
         menu.MKey = dr["MKey"].ToString();
         list.Add(menu);
     }
     dr.Close();
     return list;
 }

启动程序,查看最终效果

后台完整代码如下:

cs 复制代码
using Helper;
using ImSql.Models;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MenuDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        //定义一个递归加载方法
        private void AddMenuItems(List<MenuInfo> allMenus, MenuItem pMenu, int parentId)
        {
            //获取当前的子菜单列表
            var subList = allMenus.Where(m => m.ParentId == parentId);
            foreach (var mi in subList)
            {
                MenuItem mItem = new MenuItem();
                mItem.Header = mi.MenuName;
                if (!string.IsNullOrEmpty(mi.MKey))
                    mItem.InputGestureText = mi.MKey;
                if (pMenu != null)
                    pMenu.Items.Add(mItem);//子菜单
                else
                    menus.Items.Add(mItem);//一级菜单
                AddMenuItems(allMenus, mItem, mi.MenuId);
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            List<MenuInfo> menuList = GetMenuList();
            //调用递归方法
            AddMenuItems(menuList, null, 0);

        }



        /// <summary>
        /// 获取菜单数据
        /// </summary>
        /// <returns></returns>
        private List<MenuInfo> GetMenuList()
        {
            string sql = "select MenuId,MenuName,ParentId,MKey from MenuInfos";
            SqlDataReader dr = SqlHelper.ExecuteReader(sql, 1);
            List<MenuInfo> list = new List<MenuInfo>();
            while (dr.Read())
            {
                MenuInfo menu = new MenuInfo();
                menu.MenuId = (int)dr["MenuId"];
                menu.MenuName = dr["MenuName"].ToString();
                menu.ParentId = (int)dr["ParentId"];
                menu.MKey = dr["MKey"].ToString();
                list.Add(menu);
            }
            dr.Close();
            return list;
        }



    }
}