前段时间,有个人想做一个后台管理程序,来管理他的Helo App。单表增删改查,一个登录界面,我一口报价600元,小伙子答应了。
看一下这个后台管理是啥样子。
这个是登录界面,没什么说的,再看一下主界面。
一个简单的根据用户名,性别查询。能够创建新用户,修改用户,删除用户。
那么这么样一个需求,用什么来做呢?首先用户肯定的说不能做成cs,排除winform and wpf。现在选择的余地还有asp.net webforms和asp.net mvc,或者node.js。选择谁呢,考虑再三,我觉得还是webforms做起来最快,直接服务端控件搞起。有的人说这个webforms过时了,存在即合理,有什么过时的,钱挣到手再说。
看一下程序结构,如下。
看起来是如此的简单,一个登录一个Default.aspx,接下来我们看一下主页面吧。
(1)先是查询条件,用bootstrap的panel组件包起来。
<div class="panel panel-default"> <div class="panel-body"> <div class="row row-line"> <div class="col-md-1"> <label>用户名:</label> </div> <div class="col-md-3"> <asp:TextBox runat="server" MaxLength="20" ID="txt_UserName" CssClass="form-control" AutoComplete="off"></asp:TextBox> </div> <div class="col-md-2 text-right"> <label>性别:</label> </div> <div class="col-md-2"> <asp:DropDownList ID="ddl_Sex" runat="server" DataValueField="SexId" DataTextField="SexDisplay" CssClass="form-control"></asp:DropDownList> </div> <div class="col-md-1"> <asp:Button runat="server" Text="查询" ID="btn_Search" CssClass="btn btn-success" OnClick="btn_Search_Click" CausesValidation="false" /> </div> <div class="col-md-2" style="text-align: right"> <button type="button" onclick="showCreateModal()" class="btn btn-primary">创建用户</button> </div> <div class="col-md-1"> <asp:Button ID="btn_LogOut" runat="server" Text="注销" OnClick="btn_LogOut_Click" CssClass="btn btn-warning" /> </div> </div> </div> </div>
(2)GridView绑定数据
<div class="margin-top-10"> <asp:GridView ID="gv_UserList" CssClass="table table-striped table-bordered table-condensed table-hover" runat="server" ShowHeader="true" AutoGenerateColumns="False" DataKeyNames="UserCode" OnRowCreated="gv_UserList_RowCreated" OnRowDeleting="gv_UserList_RowDeleting" OnRowDataBound="gv_UserList_RowDataBound"> <Columns> <asp:TemplateField HeaderText="照片" ItemStyle-HorizontalAlign="Center" HeaderStyle-Width="80px"> <ItemTemplate> <img class="lazy" style="width: 50px; height: 50px" data-original="<%#DataBinder.Eval(Container.DataItem,"HeadImage") %>" /> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="UserCode" HeaderText="用户名" SortExpression="UserCode" HeaderStyle-Width="200px" /> <asp:BoundField DataField="UserPwd" HeaderText="密码" HeaderStyle-Width="120px" /> <asp:BoundField DataField="Sex" HeaderText="性别" SortExpression="Sex" HeaderStyle-Width="80px" /> <asp:BoundField DataField="Birthday" HeaderText="出生日期" DataFormatString="{0:yyyy-MM-dd}" HeaderStyle-Width="120px" /> <asp:BoundField DataField="GenerateNum" HeaderText="生成码" HeaderStyle-Width="70px" /> <asp:BoundField DataField="Source" HeaderText="注册来源" HeaderStyle-Width="70px" /> <asp:BoundField DataField="CreateDate" HeaderText="注册日期" SortExpression="CreateDate" DataFormatString="{0:yyyy-MM-dd HH:mm:ss}" HeaderStyle-Width="130px" /> <asp:TemplateField HeaderText="编辑" HeaderStyle-Width="40px"> <ItemTemplate> <button type="button" id="btn_Edit" class="btn btn-info" onclick="<%# "javascript:showModifyModal('"+ DataBinder.Eval(Container.DataItem,"UserCode")+"','"+ DataBinder.Eval(Container.DataItem,"UserPwd")+"','"+ DataBinder.Eval(Container.DataItem,"Sex")+"','"+ DataBinder.Eval(Container.DataItem,"Birthday")+"','"+ DataBinder.Eval(Container.DataItem,"HeadImageID")+"','"+ DataBinder.Eval(Container.DataItem,"HeadImage")+"')"%>"> 编辑</button> </ItemTemplate> </asp:TemplateField> <asp:CommandField HeaderText="删除" DeleteText="删除" ShowDeleteButton="True" ButtonType="Button" ControlStyle-CssClass="btn btn-danger" HeaderStyle-Width="40px" /> </Columns> <EmptyDataTemplate> <asp:Label ID="Label1" Text="无数据" runat="server" ForeColor="Red"></asp:Label> </EmptyDataTemplate> </asp:GridView> </div> <webdiyer:AspNetPager ID="pager_UserList" OnPageChanging="pager_UserList_PageChanging" runat="server" HorizontalAlign="Center" PagingButtonSpacing="0" NumericButtonCount="8" Width="100%" ShowCustomInfoSection="Left" PageIndexBoxStyle="width:19px" FirstPageText="【首页】" LastPageText="【尾页】" NextPageText="【下一页】" PrevPageText="【上一页】" NumericButtonTextFormatString="【{0}】" TextAfterPageIndexBox="页" TextBeforePageIndexBox="转到第" CustomInfoHTML="共 <font color='red'><b>%RecordCount%</b></font> 条记录 共 <font color='red'><b>%PageCount%</b></font> 页"> </webdiyer:AspNetPager>
这里第一列是用户图像列,还有个编辑列,我将其做成模板列,修改按钮会调用一个js方法弹出修改界面。在这里注意了,分页使用杨涛的AspNetPager,省时省力。在这一步,大家先记住GridView上的三个事件,RowCreated,RowDeleting,RowDataBound。顾名思义,分别是行创建结束,正要删除行,行数据绑定完成。
OK,我们接下来看一下后端cs代码。
protected void Page_Load(object sender, EventArgs e) { if (Session["UserName"] == null) { Response.Redirect("~/Login.aspx"); return; } ProcessRequest(); if (!IsPostBack) { InitDropdownList(); InitData(); InitImageList(); } }
在PageLoad事件中判断有没有登录,绑定下拉列表选项,初始化GridView数据。
private void ProcessRequest() { if (Request["action"] == "update") { DoUpdateHandler(); } else if (Request["action"] == "create") { DoCreateHandler(); } } private void InitDropdownList() { var sexList = new List<SexEntity> { new SexEntity{ SexId=-1, SexDisplay="---全部---" }, new SexEntity{ SexId=1, SexDisplay="女" }, new SexEntity{ SexId=0, SexDisplay="男" } }; ddl_Sex.DataSource = sexList; ddl_Sex.DataBind(); ddl_Sex.SelectedIndex = 0; sexList[0].SexDisplay = "---请选择---"; ddl_SetupSex.DataSource = sexList; ddl_SetupSex.DataBind(); ddl_SetupSex.SelectedIndex = 0; } private void InitData() { string userName = txt_UserName.Text.Trim(); int userSex = Convert.ToInt32(ddl_Sex.SelectedValue); int pageIndex = pager_UserList.CurrentPageIndex - 1; int pageSize = pager_UserList.PageSize; using (HeloEntities heloEntities = new HeloEntities()) { IQueryable<Users> query = heloEntities.Users; if (!string.IsNullOrEmpty(userName)) { query = query.Where(q => q.UserCode.Contains(userName)); } if (userSex >= 0) { query = query.Where(q => q.Sex == userSex); } query = query.Where(q => q.IsDisable == 0); query = query.OrderByDescending(q => q.CreateDate); var pagedData = new PagedList<Users>(query, pageIndex, pageSize); gv_UserList.DataSource = pagedData.ToList().Select(p => { return new UserModel { UserCode = p.UserCode, UserPwd = p.UserPwd, Birthday = p.Birthday, HeadImage = p.AD_DATA_DICTIONARY?.DictionaryValue, HeadImageID = p.AD_DATA_DICTIONARY?.DictionaryCode, Sex = p.Sex, Source = p.Source, GenerateNum = p.GenerateNum, CreateDate = p.CreateDate.HasValue ? p.CreateDate.Value.ToString() : string.Empty }; }).ToList(); pager_UserList.RecordCount = pagedData.TotalCount; pager_UserList.CurrentPageIndex = 0; gv_UserList.DataBind(); } } private void InitImageList() { if (Request["action"] == "getImageList") { using (HeloEntities heloEntities = new HeloEntities()) { Response.Clear(); Response.ContentType = "application/json; charset=utf-8"; var imageList = heloEntities.AD_DATA_DICTIONARY.ToList(); Response.Write(JsonConvert.SerializeObject(imageList.Select(i => new { Code = i.DictionaryCode, Value = i.DictionaryValue }).ToList())); Response.End(); } } }
当时小伙给了我数据库,看起来命名比较烂。为了图快,那我必须是EF,上面这些不用说大家都知道,我们看一下js部分。
function showModifyModal(userCode, userPwd, sex, birthDay, imageId, imageUrl) { reset(); $('#<%=txt_SetupUserName.ClientID%>').attr('readonly', true); $('#<%=txt_PassWord.ClientID%>').val(userPwd); $('#hfd_UserCode').val(userCode); $('#<%=txt_SetupUserName.ClientID%>').val(userCode); $('#<%=ddl_SetupSex.ClientID%>').val(!sex ? "-1" : sex); $('#<%=txt_BirthDay.ClientID%>').val(birthDay); $('#hfd_ImageId').val(imageId); $('#img_User').attr('src', imageUrl); $('#userModifyModal').modal('show'); }
这个是弹出修改界面代码,说了这么久,还没见到修改界面。
这是一个bootstrap modal页,点击选择图像,可以选择自己喜欢的图像。
就是一堆海里的动物,不知道为啥用户这么喜欢海里的东西,看一下这个弹出选择动物的这个界面代码。
<div class="modal fade" id="userImageModal" tabindex="-1" role="dialog" data-backdrop="true" aria-labelledby="myImageModalLabel" aria-hidden="true"> <div class="modal-dialog" style="width: 500px;"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h4 class="modal-title" id="myImageModalLabel">用户图像选择</h4> </div> <div class="modal-body"> <div class="row"> <div class="col-md-12" id="div_ImageList"> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-warning" data-dismiss="modal">关闭</button> </div> </div> </div> <!-- /.modal-content --> </div>
$.ajax({ url: 'default.aspx?action=getImageList', type: 'get', dataType: 'json', success: function (data) { if (data && data.length > 0) { $.each(data, function (obj) { $("#div_ImageList").append("<div class='col-md-2'><img style='width:60px;height:60px;padding:2px;cursor:pointer' tag='" + $(this)[0].Code + "' src='" + $(this)[0].Value + "'></img></div>"); }); $("#div_ImageList img").mouseover(function () { $(this).css("background-color", "#2aabd2"); }); $("#div_ImageList img").mouseout(function () { $(this).css("background-color", ""); }); $("#div_ImageList img").click(function () { $('#userImageModal').modal('hide'); $('#img_User').attr('src', $(this).attr('src')); $('#hfd_ImageId').val($(this).attr('tag')); }); } } });
请求到图片以后,加载到div(#div_ImageList)中。
OK,最后再看一下最早提到的那三个事件。
protected void gv_UserList_RowCreated(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { ControlCollection ctrlCollection = e.Row.Cells[e.Row.Cells.Count - 1].Controls; foreach (var ctrl in ctrlCollection) { if (ctrl is Button && (ctrl as Button).Text == "删除") { (ctrl as Button).Attributes.Add("onclick", "if(!window.confirm('确定删除吗?')) return;"); break; } } } } protected void gv_UserList_RowDeleting(object sender, GridViewDeleteEventArgs e) { string userCode = gv_UserList.DataKeys[e.RowIndex].Value.ToString(); using (HeloEntities heloEntities = new HeloEntities()) { var user = heloEntities.Users.FirstOrDefault(u => u.UserCode == userCode); if (user != null) { user.IsDisable = 1; heloEntities.SaveChanges(); InitData(); } } } protected void gv_UserList_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.DataItem == null) return; UserModel userModel = e.Row.DataItem as UserModel; if (e.Row.RowType == DataControlRowType.DataRow) { if (userModel.Sex == 1) { e.Row.Cells[3].Text = "女"; } else if (userModel.Sex == 0) { e.Row.Cells[3].Text = "男"; } else { e.Row.Cells[3].Text = "未知"; } } }
第一个是为了给删除按钮加confirm,第二个是删除该行数据的时候拿到这行数据的key:UserCode,注意GridView的DataKeyNames,就是设置Row Key的。第三个事件是该行数据绑定完成后触发,这时我们可以拿到该行绑定的对象,在这里就是为了转换男女显示。
好的,今天就到这里,只是想说任何东西存在就有使用的价值,并不是webforms就一文不值,微软就要放弃他,有时候他也能为我们挣些零花钱。
下一篇 Akka.Net组件研究(一)
匿名游客
匿名游客