为ASP.NET MVC开发一些常用插件(一)——导航栏

简介: 在WebForms中,大家应该都体会过SiteMapPath给开发带来的便利,而今格式各样的导航栏、导航菜单已经成了网站不可缺少的一部分,接下去大家会看到一个在MVC下使用的,并且符合MVC设计规范的导航栏“插件”,以在MVC中取代之前SiteMapPath的应用。

WebForms中,大家应该都体会过SiteMapPath给开发带来的便利,而今格式各样的导航栏、导航菜单已经成了网站不可缺少的一部分,接下去大家会看到一个在MVC下使用的,并且符合MVC设计规范的导航栏“插件”,以在MVC中取代之前SiteMapPath的应用。

首先我们还是明确一下这个插件的意义和需要完成的基本功能:

问:既然有SiteMapPath,为什么还要重复开发一个同样功能的导航栏?

答:没错,SiteMapPath服务器控件在MVC(以下无特别说明都专指ASP.NET MVC)中仍然可以很好地“显示”,但是显然无法很好满足C-V结构的分离,SiteMapPath控件依赖于aspx页面,而在MVC中,早在aspx页面执行之前,几乎所有数据都应该在Controller处理完成,“打包”给ViewData这就要求这个控件能够同时在ControllerView中被很好地控制,并且View主要只起到显示的作用。还有一点就是SiteMapPath默认的sitemap格式已经无法满足MVChttp请求的规则,使得无法很好地进行控制。

问:新开发的导航栏有哪些功能?

答:

1、完全兼容原有WebForms项目下的Web.sitemap文件格式,即当网站中同时存在MVCWebForms项目时, 可以共享sitemap文件。但须按照MVC的执行方式对原有文件稍加补充。

2、自动从Web.sitemap获得当前页面(Controller,Action)对应的网站地图位置,自动生成导航条, 使用时不需要编写任何代码。

3、根据MVCController-Action规则自动创建对应链接,也可自由设置,包括只显示文字,不使用连接等。

4、可以完全或部分手动设置、增减节点。

5、可以限制节点显示层数。

以上的大部分功能都是在SiteMapPath可实现的,但是我们已经不再需要PostBack功能的设置。

遵照这些前提,我给大家展示一下我的实现方法:

一、建立全局共享的Model层的NavigationInfo,包含在Models/ExtentionEntity.cs

public   class  NavigationInfo

        
{

            
public string Title setget; }

            
public string ActionName setget; }

            
public string ControllerName setget; }

            
public object Values setget; }

            
public void SetNavInfo(string title, string actionName, string controllerName, object values)

            
{

                Title 
= title;

                ActionName 
= actionName;

                ControllerName 
= controllerName;

                Values 
= values;

            }


            
public NavigationInfo()

            
{ }

            
public NavigationInfo(string title, string actionName, string controllerName, object values)

            
{

                
this.SetNavInfo(title, actionName, controllerName, values);

            }


            
public NavigationInfo(string title, string actionName, string controllerName)

            
{

                
this.SetNavInfo(title, actionName, controllerName, null);

            }


            
public NavigationInfo(string title, string actionName, object values)

            
{

                
this.SetNavInfo(title, actionName, null, values);

            }


            
public NavigationInfo(string title)

            
{

                
this.SetNavInfo(title, nullnullnull);

            }


        }


   
    其中,TitleActionNameControllerNameValues分别对应View页面ActionLink需要的链接文字、actioncontrollervalues。里面也提供了对NavigationInfo4种重写的方法,以便和ActionLink的参数重写尽量配套,在适应使用习惯的同时也提供了更大的灵活性。

二、创建BaseViewData,所有继承了这个类的ViewData都将获得NavigationInfo属性。Models/BaseViewData.cs

    public   class  BaseViewData

    
{

        
public string Title getset; }//这个Title现在这儿埋个伏笔,我会在下文中说明,和导航拦没有太直接关系

        
public List<ExtentionEntity.NavigationInfo> NavInfo getset; }

    }

    三、创建Views/Shared/Navigation.ascx,供页面调用。

注:这里我使用了用户控件的形式是因为考虑到开发时实际调用导航栏的页面不会太多(一般都只在母板页),如果你觉引用的比较多,这样不太方便,也可以加到HtmlHelper中,其中要执行的代码是一样的:

<% @ Control Language="C#" AutoEventWireup="true" CodeBehind="Navigation.ascx.cs"

    Inherits
="MVCTools.Views.Shared.Navigation" 
%>

< div  id ="Navigation"  class ="Navigation" >

    
<%  

        
if (ViewData.ContainsDataItem("navInfo")) {

            System.Collections.Generic.List
<MVCTools.Models.ExtentionEntity.NavigationInfo> navInfo = new System.Collections.Generic.List<MVCTools.Models.ExtentionEntity.NavigationInfo>();

            
if (ViewData["navInfo"== null || ((System.Collections.Generic.List<MVCTools.Models.ExtentionEntity.NavigationInfo>)ViewData["navInfo"]).Count == 0)

            {

                navInfo 
= MVCTools.Common.Navigation.GetAutoNavigationInfo();

            }

            
else

            {

                navInfo 
= (System.Collections.Generic.List<MVCTools.Models.ExtentionEntity.NavigationInfo>)ViewData["navInfo"];

            }

%> 您的位置: <%

             
int i = 0;

             foreach (MVCTools.Models.ExtentionEntity.NavigationInfo nav in navInfo)

             {

                 
if (++> 1)

                 {
%> &nbsp;&nbsp; > <% --//TODO:间隔标记可以扩展为用户自定义-- %> &nbsp;&nbsp; <% } %>

<%  if (nav.Values != null)

   {

        
if (!string.IsNullOrEmpty(nav.ActionName))//if (nav.Values.ToAttributeList().Contains("controller"))

           {
%><% =  Html.ActionLink(nav.Title,nav.ActionName, nav.Values) %><% }

           
else

           {
%><% =  nav.Title %><% }

   }

   
else if (!string.IsNullOrEmpty(nav.ActionName))

       {
%><% =  Html.ActionLink(nav.Title, nav.ActionName, nav.ControllerName) %><% }

       
else

       { 
%><% =  nav.Title %><% }

         } 
%>

<%  }  %>

</ div >

在aspx中,我们只需要这样引用就行了:

<!--  导航条  -->

<% =  Html.RenderUserControl( " /Views/Shared/Navigation.ascx " ) %>

    四、准备工作基本做好了,下面来看一下在Controller中如何对导航栏灵活控制。

在此之前,我需要在Common中建了一个专门负责处理NavigationInfo的类Common/Navigation.cs

Code

上面可以看到,相比使用XMLDocument的传统方式,Linq to XML大大简化了对XML的操作。其中关键的地方都作了比较详细的注释,欢迎大家提出建议或批评!

下面是上述方法在Controller中的使用。

注:这里还有一个注意点:虽然NavigationInfo中的Title提供直接在ActionLink中显示的text内容,但是建议不要在Controller中定义的过死,否则可能导致C-V数据的脱节,我在Controller演示设置NavigationInfo的功能,并不在于要在Controller中就把导航栏HTML代码输出,只是输出一个包含节点信息的ListViewDate,让其在View中具体生成。

我举NavController为例,里面有一个Actionvoid More(string type)

public   void  More( string  type)

        
{

            Models.MoreViewData vd 
= new MVCTools.Models.MoreViewData();

            
switch (type)

            
{

                
case "manual"://完全手动创建

                    vd.SomePageInfo 
= "完全手动创建";

                    vd.NavInfo 
= new List<MVCTools.Models.ExtentionEntity.NavigationInfo>()

                    
{

                        
new ExtentionEntity.NavigationInfo("手动创建第一节","Index","Home"),

                        
new ExtentionEntity.NavigationInfo("手动创建第二节","Index","Home"),

                        
new ExtentionEntity.NavigationInfo("手动创建第三节","Index","Home"),

                        
new ExtentionEntity.NavigationInfo("手动创建第四节","Index","Home"),

                        
//只设Title时,此节点不会显示为链接

                        
new ExtentionEntity.NavigationInfo("手动创建第五节"),

                    }
;

                    
//最后插入“根节点”,使用扩展方法

                    vd.NavInfo.Insert(
new ExtentionEntity.NavigationInfo("手动创建的根节点""Index""Home"), 1);

                    
//以下方法和上一句等效

                    
//vd.NavInfo.Insert(0,new ExtentionEntity.NavigationInfo("手动创建的根节点", "Index", "Home"));

                    
break;

                
case "add"://增加节点

                    vd.SomePageInfo 
= "自动获取基础上增加节点";

                    vd.NavInfo 
= Navigation.GetAutoNavigationInfo();//自动获取全部节点

                    
//在前面插入

                    vd.NavInfo.Insert( 
new ExtentionEntity.NavigationInfo("手动创建第一个"),-1);

                    
//在后面插入

                    vd.NavInfo.Add(
new ExtentionEntity.NavigationInfo("手动创建第二个"));

                    vd.NavInfo.Add(
new ExtentionEntity.NavigationInfo("手动创建第三个"));

                    
//以下方法和上一句等效

                    
//vd.NavInfo.Insert(new ExtentionEntity.NavigationInfo("手动创建第三个"), 0);

                    
break;

                
case "subtract"://限制、扣除节点

                    vd.SomePageInfo 
= "自动获取基础上限制节点,只显示到第2层";

                    vd.NavInfo 
= Navigation.GetAutoNavigationInfo(2);

                    
break;

                
default:

                    
//自动获取,什么都不用做

                    vd.SomePageInfo 
= "完全自动读取Web.sitemap";

                    
break;

            }


            RenderView(
"More",vd);

        }


通过上面case4种情况我向大家演示了文章开头我们需要完成的5项基本功能,其中如果你不需要对导航栏信息修改,让其自动获取的话,只要传递一个BaseViewData给页面,什么都不用做:

 

public   void  More()
        
{
            MoreViewData vd 
= new  MoreViewData ();
//Your Code
            RenderView("More ", vd);
        }

 

而接下去在aspx页面(Views)中,你可以什么都不要做,如果需要获取信息或者修改的话只需要查看ViewData.NavInfo或者ViewData[“NavInfo”]就行了。

这里要小说一下上面提到的BaseViewDataTitle参数,是用于网页标题Title的显示,由于Title基本属于View层面的东西,在这里设Title主要是方便ControllerView的沟通,具体设置也可以在View中完成(我还是觉得在程序员和美工有很好沟通的情况下,在Controller先设置好基础部分更方便一些,而且不用劳烦每个aspx文件都对title设置,那样有时实在很辛苦)。这个Title你只需要设置最“个性化”的信息,全局的包括每个母板的特定信息会自动加上。有了这个功能,你还可以自己进行一些扩展,比如:把导航栏的最后一个节点的信息作为标题等等。由于和导航栏没有非常直接的关系,这里我暂不多加论述,具体应用你可以在我的Demo中的母板页文件看到(注意.Master.cs文件)

这里是上面代码的Demo下载:/Files/szw/MVCTools_mvc.rar 

补充一下,对于sitemap的变化,只是为每个节点多加了两个controller和action属性,以控制节点显示的链接,具体大家可以看Demo中的Web.sitemap

    这个导航栏的实现很简单,希望能够发上来抛砖引玉,也省去一些朋友重复劳动之苦。如果有任何不周之处,还望大家见谅和赐教!

 

QQ:498977166

http://szw.cnblogs.com/
研究、探讨.NET开发
转载请注明出处和作者,谢谢!

 


微信开发深度解析:微信公众号、小程序高效开发秘籍
Senparc官方教程《微信开发深度解析:微信公众号、小程序高效开发秘籍》,耗时2年精心打造的微信开发权威教程,点击这里,购买正版

 

目录
相关文章
|
20天前
|
SQL 小程序 API
如何运用C#.NET技术快速开发一套掌上医院系统?
本方案基于C#.NET技术快速构建掌上医院系统,结合模块化开发理念与医院信息化需求。核心功能涵盖用户端的预约挂号、在线问诊、报告查询等,以及管理端的排班管理和数据统计。采用.NET Core Web API与uni-app实现前后端分离,支持跨平台小程序开发。数据库选用SQL Server 2012,并通过读写分离与索引优化提升性能。部署方案包括Windows Server与负载均衡设计,确保高可用性。同时针对API差异、数据库老化及高并发等问题制定应对措施,保障系统稳定运行。推荐使用Postman、Redgate等工具辅助开发,提升效率与质量。
|
2月前
|
人工智能 芯片
D1net阅闻|OpenAI员工疯狂暗示,内部已成功开发ASI?被曝训出GPT-5但雪藏
D1net阅闻|OpenAI员工疯狂暗示,内部已成功开发ASI?被曝训出GPT-5但雪藏
|
4月前
|
Linux API C#
基于 .NET 开发的多功能流媒体管理控制平台
基于 .NET 开发的多功能流媒体管理控制平台
83 9
|
4月前
|
Web App开发 前端开发 调度
一款基于 .NET + Blazor 开发的智能访客管理系统
一款基于 .NET + Blazor 开发的智能访客管理系统
|
4月前
|
前端开发 JavaScript C#
基于.NET8+Vue3开发的权限管理&个人博客系统
基于.NET8+Vue3开发的权限管理&个人博客系统
|
4月前
|
网络协议 C#
基于.NET WinForm开发的一款硬件及协议通讯工具
基于.NET WinForm开发的一款硬件及协议通讯工具
|
4月前
|
监控 前端开发 API
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
113 5
|
11月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
275 0
|
8月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
103 0
|
存储 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(五)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面,商品详情等功能的开发,今天继续讲解购物车功能开发,仅供学习分享使用,如有不足之处,还请指正。
203 0

热门文章

最新文章