4. 3. 新增编辑成绩视图AddEditScore
新增编辑成绩视图,主要用于对成绩的修改和新增,可通过查询页面的新增按钮和具体成绩的编辑按钮弹出对应窗口。如下所示:
<UserControl x:Class="SIMS.ScoreModule.Views.AddEditScore" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:SIMS.ScoreModule.Views" xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:mahApps ="http://metro.mahapps.com/winfx/xaml/controls" xmlns:prism="http://prismlibrary.com/" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <prism:Dialog.WindowStyle> <Style TargetType="Window"> <Setter Property="Width" Value="600"></Setter> <Setter Property="Height" Value="400"></Setter> </Style> </prism:Dialog.WindowStyle> <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" /> <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources> <i:Interaction.Triggers> <i:EventTrigger EventName="Loaded"> <i:InvokeCommandAction Command="{Binding LoadedCommand}"></i:InvokeCommandAction> </i:EventTrigger> </i:Interaction.Triggers> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.2*"></ColumnDefinition> <ColumnDefinition Width="Auto"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="0.2*"></ColumnDefinition> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <TextBlock Text="学生" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Margin="3"></TextBlock> <ComboBox Grid.Row="0" Grid.Column="2" MinWidth="120" Height="35" ItemsSource="{Binding Students}" mahApps:TextBoxHelper.ClearTextButton="True" SelectedItem="{Binding Student}"> <ComboBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Name}"></TextBlock> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> <TextBlock Text="课程" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="3"></TextBlock> <ComboBox Grid.Row="1" Grid.Column="2" MinWidth="120" Height="35" ItemsSource="{Binding Courses}" mahApps:TextBoxHelper.ClearTextButton="True" SelectedItem="{Binding Course}"> <ComboBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Name}"></TextBlock> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> <TextBlock Text="成绩" Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Margin="3"></TextBlock> <TextBox Grid.Row="2" Grid.Column="2" MinWidth="120" Height="35" VerticalAlignment="Center" Margin="3" Text="{Binding Score.Score}"></TextBox> <StackPanel Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center" Margin="3"> <Button Content="取消" Margin="5" MinWidth="120" Height="35" Style="{DynamicResource MahApps.Styles.Button.Square.Accent}" Command="{Binding CancelCommand}"></Button> <Button Content="保存" Margin="5" MinWidth="120" Height="35" Style="{DynamicResource MahApps.Styles.Button.Square.Accent}" Command="{Binding SaveCommand}"></Button> </StackPanel> </Grid> </UserControl>
4.4. 新增编辑成绩ViewModel
AddEditScoreViewModel是对页面具体功能的业务封装,主要是对应成绩信息的保存,也包括数据绑定和命令绑定等内容,与其他模块不同之处,在于此模块关联学生和课程信息,需要绑定下拉框数据源。具体如下所示:
namespace SIMS.ScoreModule.ViewModels { public class AddEditScoreViewModel : BindableBase, IDialogAware { #region 属性和构造函数 /// <summary> /// 当前实体 /// </summary> private ScoreEntity score; public ScoreEntity Score { get { return score; } set { SetProperty(ref score , value); } } /// <summary> /// 下拉框选择的学生 /// </summary> private StudentEntity student; public StudentEntity Student { get { return student; } set { SetProperty(ref student , value); } } /// <summary> /// 学生列表 /// </summary> private List<StudentEntity> students; public List<StudentEntity> Students { get { return students; } set { SetProperty(ref students, value); } } private CourseEntity course; public CourseEntity Course { get { return course; } set {SetProperty(ref course , value); } } /// <summary> /// 课程列表 /// </summary> private List<CourseEntity> courses; public List<CourseEntity> Courses { get { return courses; } set { SetProperty(ref courses, value); } } public AddEditScoreViewModel() { } #endregion #region Command private DelegateCommand loadedCommand; public DelegateCommand LoadedCommand { get { if (loadedCommand == null) { loadedCommand = new DelegateCommand(Loaded); } return loadedCommand; } } private void Loaded() { LoadStudents(); LoadCourses(); //如果有班长,则为班长赋值 if (Score.StudentId > 0) { this.Student = this.Students?.FirstOrDefault(r => r.Id == Score.StudentId); } if (Score.CourseId > 0) { this.Course = this.Courses?.FirstOrDefault(r=>r.Id == Score.CourseId); } } private DelegateCommand cancelCommand; public DelegateCommand CancelCommand { get { if (cancelCommand == null) { cancelCommand = new DelegateCommand(Cancel); } return cancelCommand; } } private void Cancel() { RequestClose?.Invoke((new DialogResult(ButtonResult.Cancel))); } private DelegateCommand saveCommand; public DelegateCommand SaveCommand { get { if (saveCommand == null) { saveCommand = new DelegateCommand(Save); } return saveCommand; } } private void Save() { if (Score != null) { Score.CreateTime = DateTime.Now; Score.LastEditTime = DateTime.Now; if (Student != null) { Score.StudentId = Student.Id; } if (Course != null) { Score.CourseId = Course.Id; } bool flag = false; if (Score.Id > 0) { flag = ScoreHttpUtil.UpdateScore(Score); } else { flag = ScoreHttpUtil.AddScore(Score); } if (flag) { RequestClose?.Invoke((new DialogResult(ButtonResult.OK))); } } } #endregion #region 函数 /// <summary> /// 加载学生列表 /// </summary> private void LoadStudents() { this.Students = new List<StudentEntity>(); var pagedRequst = StudentHttpUtil.GetStudents(null, null, 1, -1); var entities = pagedRequst.items; Students.AddRange(entities); } /// <summary> /// 加载课程列表 /// </summary> private void LoadCourses() { this.Courses = new List<CourseEntity>(); var pagedRequst = CourseHttpUtil.GetCourses(null, null, 1, -1); var entities = pagedRequst.items; Courses.AddRange(entities); } #endregion } }
注意:弹出窗口实现方法与其他模块通用,所以此处略去。
5. 成绩管理示例效果图
经过上述步骤后,成绩管理模块就开发完成,运行VS后,效果如下所示:
系统管理模块
1. 系统管理模块核心代码
系统管理模块,主要包含四个部分,用户管理,角色管理,菜单管理,个人信息。因篇幅有限,暂时仅列出主要内容:
从数据库读取用户所属的权限,代码如下所示:
public List<UserRight> GetUserRights(int? userId) { if (userId != null) { var query = from u in dataContext.UserRoles join r in dataContext.Roles on u.RoleId equals r.Id join x in dataContext.RoleMenus on r.Id equals x.RoleId join m in dataContext.Menus on x.MenuId equals m.Id where u.UserId == userId select new UserRight { Id = m.Id, RoleName = r.Name, MenuName = m.Name, Url = m.Url,Icon=m.Icon, ParentId = m.ParentId, SortId = m.SortId }; return query.ToList(); } return null; }
在客户端获取后,转换成导航菜单对象即可,如下所示:
public NavigationViewModel(IEventAggregator eventAggregator) { this.eventAggregator = eventAggregator; navItems = new List<HamburgerMenuItemBase>(); var userRights = RoleHttpUtil.GetUserRights(UserInfo.Instance.Id); var parents = userRights.Where(x => x.ParentId == null).OrderBy(r=>r.SortId); foreach (var parent in parents) { navItems.Add(new HamburgerMenuHeaderItem() { Label = parent.MenuName }); var subItems = userRights.Where(r=>r.ParentId==parent.Id).OrderBy(r=>r.SortId); foreach (var subItem in subItems) { navItems.Add(new HamburgerMenuGlyphItem() { Label = subItem.MenuName, Tag = subItem.Url, Glyph = subItem.Icon }); } } UserInfo.Instance.Roles = String.Join(',', userRights.Select(r=>r.RoleName).Distinct().ToList()); }
2. 系统管理模块示例截图
关于系统管理模块示例截图如下所示:
个人信息,显示个人基础信息,如下所示:
用户管理,比其他列表多了一个授权按钮,主要用于为用户分配角色如下所示:
角色管理模块,比其他列表多了一个分配按钮,主要用于为分配角色对应的菜单如下所示:
菜单管理,菜单管理模块,主要用于管理菜单信息,与其他模块不同的是,需要配置图标,如下所示:
总结
通过本篇文章的成绩管理模块,系统管理模块,以及前两篇文章中的课程管理模块,班级管理模块,学生管理模块,不难发现,每一个模块的开发都是由列表DataGrid,文本框TextBox,下拉框Combox,单选按钮RadioButton,按钮Button等组成的,虽功能略有差异,但总归万变不离其宗。开发方法也大同小异,复杂的功能都是普通的功能累加起来的。这也是本系列文章由浅入深的渐进安排。希望能够抛砖引玉,不局限于某一功能,而是能够举一反三,自我理解,以达到自我开发的能力。
至此,整个WPF开发学生信息管理系统系列已完毕。