Menu:菜单控件应用实例
Menu : Windows 菜单控件,该控件可用于按层次组织与命令和事件处理程序关联的元素。
父类:MenuBase - ItemsControl
属性:IsMainMenu 菜单是否接收主菜单激活通知(Alt或F10键)
Menu中的菜单项:MenuItem --菜单中可选择的项
父类:HeaderedItemsControl
MenuItem的属性:HeaderedItemsControl
Icon 项图标
InputGestureText 设置描述输入的笔势(快捷键)
Command 与菜单项关联的命令
Header 菜单项文本
IsChecked 项是否选中
IsSubmenuOpen 子菜单是否处于打开
IsHighlighted 是否突出显示
事件:Click
实现效果
创建数据库及表及添加初始数据
打开数据库,记住自己的服务器名称;
输入下面代码创建数据库及表及添加初始数据
--判断数据库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程序
<Windowx: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><MenuName="menus"Width="500"Height="37"HorizontalAlignment="Left"VerticalAlignment="Top"Background="#FF0ABEFF" /></Grid>
</Window>
在App.config 添加连接数据库的资源字典
<connectionStrings><add name="connStr" connectionString="Server=DESKTOP-JRTKHSS\SQLEXPRESS;DataBase=SqlData;Uid=sa;Pwd=123456" /></connectionStrings>
添加文件夹dbhelper及工具类CommandInfo、SqlHelper
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;}}
}
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 返回上一次插入记录时自动产生的IDint result = 0;//返回结果using (SqlConnection conn = new SqlConnection(connStr)){//执行脚本的对象cmdSqlCommand cmd = BuilderCommand(conn, sql, cmdType, null, parameters);result = cmd.ExecuteNonQuery();//执行T-SQL并返回受影响行数cmd.Parameters.Clear();}//using原理:类似于try finallyreturn 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)){//执行脚本的对象cmdSqlCommand 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;elsecmd.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;elsecmd.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));elsereturn 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
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
在页面后台代码中添加如下代码
//定义一个递归加载方法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);//子菜单elsemenus.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;}
启动程序,查看最终效果
后台完整代码如下:
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);//子菜单elsemenus.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;}}
}