學用MVC4做網站三:3.1添加欄目


好幾天沒時間寫了。今天有寫時間在學一點。

今天狀態也不是很好,暈暈沉沉的寫吧。

一、用戶

二、用戶組

三、欄目

3.1添加欄目

首先添加【CategoryController】控制器,

那么我想我的視圖里,首先顯示的應該是欄目類型,這里應該是一個下拉框,用戶可以選擇“一般欄目”,“單頁欄目”,“外部鏈接”。那么首先應該在【CategoryController】添加一個屬性,用來返回欄目類型列表。

#region Attribute
        public List<SelectListItem> TypeSelectList
        {
            get
            {
                List<SelectListItem> _items = new List<SelectListItem>();
                _items.Add(new SelectListItem { Text = CategoryType.一般欄目.ToString(), Value = ((int)CategoryType.一般欄目).ToString() });
                _items.Add(new SelectListItem { Text = CategoryType.單頁欄目.ToString(), Value = ((int)CategoryType.單頁欄目).ToString() });
                _items.Add(new SelectListItem { Text = CategoryType.外部鏈接.ToString(), Value = ((int)CategoryType.外部鏈接).ToString() });
                return _items;
            }
        }
        #endregion

其次,用戶應該可以選擇內容模型,內容模型是什么?

內容模型就是這個欄目下可以添加內容的模型名稱?這個模型名稱對應的就是Models中間的模型類。為了更好的表述在系統中添加模塊“Module ”的概念。模塊用來指系統中用來實現相應功能的塊,想新聞模塊,文章模塊,留言模塊,圖片模塊,產品模塊,服務模塊等等,每個模塊對應相應的模型和控制器,用來實現設想中的功能。系統中預置的模塊用戶應該可以設置啟用還是關閉。

第一應該添加內容模型類

using System.ComponentModel.DataAnnotations;

namespace Ninesky.Models
{
    /// <summary>
    /// 內容模塊
    /// </summary>
    public class Module
    {
        [Key]
        public int ModuleId { get; set; }
        /// <summary>
        /// 模塊名稱
        /// </summary>
        [Required(ErrorMessage="×")]
        [Display(Name="模塊名稱")]
        public string Name { get; set; }
        /// <summary>
        /// 模塊模型
        /// </summary>
        [Required(ErrorMessage = "×")]
        [Display(Name = "模塊模型")]
        public string Model { get; set; }
        /// <summary>
        /// 啟用模塊
        /// </summary>
        [Required(ErrorMessage = "×")]
        [Display(Name = "啟用模塊")]
        public bool Enable { get; set; }
        /// <summary>
        /// 說明
        /// </summary>
        [Required(ErrorMessage = "×")]
        [Display(Name = "說明")]
        public string Description { get; set; }

    }
}

既然有模塊類,就應該有模塊類的數據處理類ModuleRepository,這塊功能暫時留在后面來寫,先最簡單的實現List(bool enable)函數讓其能顯示模塊列表。

using Ninesky.Models;
using System.Collections.Generic;
using System.Linq;

namespace Ninesky.Repository
{
    public class ModuleRepository
    {
        public IQueryable<Module> List(bool enable)
        {
            List<Module> _module = new List<Module>();
            _module.Add(new Module { Name = "新聞模塊", Model = "News", Enable = true, Description = "新聞模塊" });
            _module.Add(new Module { Name = "文章模塊", Model = "Article", Enable = true, Description = "文章模塊" });
            return _module.AsQueryable();
        }
    }
}

簡單吧。模塊功能以后再寫吧,先為了添加欄目顯示兩個固定的模塊,

那么后續我們要在控制器中添加[ManageAdd]action

[AdminAuthorize]
        public ActionResult ManageAdd()
        {
            ModuleRepository _moduleRsy = new ModuleRepository();
            var _modules = _moduleRsy.List(true);
            List<SelectListItem> _slimodule = new List<SelectListItem>(_modules.Count());
            foreach (Module _module in _modules)
            {
                _slimodule.Add(new SelectListItem { Text = _module.Name, Value = _module.Model });
            }
            ViewData.Add("Model", _slimodule);
            ViewData.Add("Type", TypeSelectList);
            return View();
        }

然后添加添加數據處理函數

[AdminAuthorize]
        [HttpPost]
        public ActionResult ManageAdd(Category category)
        {
            categoryRsy = new CategoryRepository();
            if (categoryRsy.Add(category))
            {
                Notice _n = new Notice { Title = "添加欄目成功", Details = "您已經成功添加[" + category.Name + "]欄目!", DwellTime = 5, NavigationName = "欄目列表", NavigationUrl = Url.Action("ManageList", "Cayegory") };
                return RedirectToAction("ManageNotice", "Prompt", _n);
            }
            else
            {
                Error _e = new Error { Title = "添加欄目失敗", Details = "在添加欄目時,未能保存到數據庫", Cause = "系統錯誤", Solution = Server.UrlEncode("<li>返回<a href='" + Url.Action("ManageAdd", "Cayegory") + "'>添加欄目</a>頁面,輸入正確的信息后重新操作</li><li>聯系網站管理員</li>") };
                return RedirectToAction("ManageError", "Prompt", _e);
            }
        }

現在開始做視圖部分了。

在[ManageAdd]action上點右鍵添加視圖,

@model Ninesky.Models.Category

@{
    ViewBag.Title = "ManageAdd";
    Layout = "~/Views/Layout/_Manage.cshtml";
}

<div class="left">
    <div class="top"></div>
    左側列表
</div>
<div class="split"></div>
<div class="workspace">
    <div class="inside">
        <div class="notebar">
            <img alt="" src="~/Skins/Default/Manage/Images/Category.gif" />添加欄目
        </div>

        @using (Html.BeginForm())
        {
            @Html.ValidationSummary(true)

            <fieldset>
                <legend>欄目</legend>
                <ul>
                    <li>
                        <div class="editor-label">
                            @Html.LabelFor(model => model.Type)
                        </div>
                        <div class="editor-field">
                            @Html.DropDownList("Type")
                            @Html.ValidationMessageFor(model => model.Type)
                            @Html.DisplayDescriptionFor(model => model.Type)
                        </div>
                    </li>
                    <li>
                        <div class="editor-label">
                            @Html.LabelFor(model => model.Name)
                        </div>
                        <div class="editor-field">
                            @Html.EditorFor(model => model.Name)
                            @Html.ValidationMessageFor(model => model.Name)
                            @Html.DisplayDescriptionFor(model => model.Name)
                        </div>
                    </li>
                    <li>
                        <div class="editor-label">
                            @Html.LabelFor(model => model.ParentId)
                        </div>
                        <div class="editor-field">
                            @Html.EditorFor(model => model.ParentId)
                            @Html.ValidationMessageFor(model => model.ParentId)
                            @Html.DisplayDescriptionFor(model => model.ParentId)
                        </div>
                    </li>
                    <li id="li_model">
                        <div class="editor-label">
                            @Html.LabelFor(model => model.Model)
                        </div>
                        <div class="editor-field">
                            @Html.DropDownList("Model")
                            @Html.ValidationMessageFor(model => model.Model)
                            @Html.DisplayDescriptionFor(model => model.Model)
                        </div>
                    </li>
                    <li id="li_categoryview">
                        <div class="editor-label">
                            @Html.LabelFor(model => model.CategoryView)
                        </div>
                        <div class="editor-field">
                            @Html.EditorFor(model => model.CategoryView)
                            @Html.ValidationMessageFor(model => model.CategoryView)
                            @Html.DisplayDescriptionFor(model => model.CategoryView)
                        </div>
                    </li>
                    <li id="li_contentview">
                        <div class="editor-label">
                            @Html.LabelFor(model => model.ContentView)
                        </div>
                        <div class="editor-field">
                            @Html.EditorFor(model => model.ContentView)
                            @Html.ValidationMessageFor(model => model.ContentView)
                            @Html.DisplayDescriptionFor(model => model.ContentView)
                        </div>
                    </li>
                    <li id="li_nav">
                        <div class="editor-label">
                            @Html.LabelFor(model => model.Navigation)
                        </div>
                        <div class="editor-field">
                            @Html.EditorFor(model => model.Navigation)
                            @Html.ValidationMessageFor(model => model.Navigation)
                            @Html.DisplayDescriptionFor(model => model.Navigation)
                        </div>
                    </li>
                    <li>
                        <div class="editor-label">
                            @Html.LabelFor(model => model.Order)
                        </div>
                        <div class="editor-field">
                            @Html.EditorFor(model => model.Order)
                            @Html.ValidationMessageFor(model => model.Order)
                            @Html.DisplayDescriptionFor(model => model.Order)
                        </div>
                    </li>
                    <li>
                        <div class="editor-label">
                        </div>
                        <div class="editor-field">
                            <input type="submit" value="添加" />
                        </div>
                    </li>
                </ul>
            </fieldset>
        }
    </div>
</div>
<div class="clear"></div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

這里給一些<li>添加id屬性,實現用戶在顯示不同的欄目類型的時候顯示不同的項目。

在ManageAdd.cshtml底部添加腳本

<script type="text/javascript">
     Details();
    $("#Type").change(function () {
        Details();
    });
    function Details() {
        var v = $("#Type").val();
        if (v == "0") {
            $("#li_model").show();
            $("#li_categoryview").show();
            $("#li_contentview").show();
            $("#li_nav").hide();
        }
        else if (v == "1") {
            $("#li_model").hide();
            $("#li_categoryview").show();
            $("#li_contentview").hide();
            $("#li_nav").hide();
        }
        else if (v == "2") {
            $("#li_model").hide();
            $("#li_categoryview").hide();
            $("#li_contentview").hide();
            $("#li_nav").show();
        }
    }
</script>

從瀏覽器中看一下。父欄目這里還有些問題,設想中這里應該是一個下拉框,用戶可以選擇已存在欄目類型為一般欄目的欄目做父欄目。這里需要下拉樹形列表,設想中應該是這個樣子,是一個下拉列表和屬性列表框的組合框。

image

html中沒有這種類型的控件,mcv4 中帶的jquery UI是一個比較好的庫,本身包含一定的控件,並且可以自己擴展,但是他缺少一些像,數據表(datagirdview),樹形控件(tree),樹形組合控件(combotree)等,且jqueryui的式樣也不太好變換,決定丟棄jqueryui,而是用easyui(相對jqueryui功能更全面,更容易控制式樣),在“引用”上點右鍵選擇管理NuGet程序包

image

在已安裝的包->全部,選擇Jquery Ui點擊卸載。

http://www.jeasyui.com/選在最新版本,在項目的/Scripts文件夾中新建EasyUi文件夾,將easyui中的一下文件夾復制到該文件夾。

image

打開App_Start\BundleConfig.cs,刪除jqueryui相關項,添加

bundles.Add(new ScriptBundle("~/bundles/EasyUi").Include(
                        "~/Scripts/EasyUi/easyloader.js"));

bundles.Add(new StyleBundle("~/EasyUi/icon").Include("~/Scripts/EasyUi/themes/icon.css"));

兩項,使該文檔看起來如下:

using System.Web;
using System.Web.Optimization;

namespace Ninesky
{
    public class BundleConfig
    {
        // 有關 Bundling 的詳細信息,請訪問 http://go.microsoft.com/fwlink/?LinkId=254725
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/EasyUi").Include(
                        "~/Scripts/EasyUi/easyloader.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.unobtrusive*",
                        "~/Scripts/jquery.validate*"));

            // 使用 Modernizr 的開發版本進行開發和了解信息。然后,當你做好
            // 生產准備時,請使用 http://modernizr.com 上的生成工具來僅選擇所需的測試。
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new StyleBundle("~/Skins/css").Include("~/Skins/Default/Style.css"));
            bundles.Add(new StyleBundle("~/Skins/usercss").Include("~/Skins/Default/User.css"));
            bundles.Add(new StyleBundle("~/Skins/ManageCss").Include("~/Skins/Default/Manage/Style.css"));
            bundles.Add(new StyleBundle("~/EasyUi/icon").Include("~/Scripts/EasyUi/themes/icon.css"));
        }
    }
}

這里會用到easyui的combotree。

查閱了官方文檔,數據格式為

Tree Data Format

Every node can contains following properties:

  • id: node id, which is important to load remote data
  • text: node text to show
  • state: node state, 'open' or 'closed', default is 'open'. When set to 'closed', the node have children nodes and will load them from remote site
  • checked: Indicate whether the node is checked selected.
  • attributes: custom attributes can be added to a node
  • children: an array nodes defines some children nodes

那么在Models文件夾里新家Ui文件夾,該文件夾用來控件數據相關的模型,添加Tree類

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Ninesky.Models.Ui
{
    /// <summary>
    /// 樹形控件數據
    /// </summary>
    public class Tree
    {
        /// <summary>
        /// Id
        /// </summary>
        public int id { get; set; }
        /// <summary>
        /// 文本
        /// </summary>
        public string text { get; set; }
        /// <summary>
        ///  節點狀態:'open'或'closed',默認'open'。
        /// </summary>
        public string state { get; set; }
        /// <summary>
        /// 圖標
        /// </summary>
        public string iconCls { get; set; }
        /// <summary>
        /// 子節點
        /// </summary>
        public List<Tree> children { get; set; }
    }
}

 

打開~/Scripts/EasyUi/themes/icon.css文件

在底部添加代碼

.icon-general {
    background: url('icons/ns_general.png') no-repeat !important;
}

切記一定記得加!important來調整css的優先級。easyui會將icon-general這個類添加在列表項的最后,如果不加這句'icons/ns_general.png'圖標將不會顯示。

選擇一個16*16的圖表命名為ns_general.png,並復制到一下文件夾

image

這里要用遞歸的方式調取一般欄目的樹形結構:打開CategoryRepository.cs。在底部添加兩個函數

/// <summary>
        /// 欄目列表
        /// </summary>
        /// <param name="model">模型名稱</param>
        /// <returns></returns>
        public IQueryable<Category> List(string model)
        {
            return dbContext.Categorys.Where(c => c.Model == model).OrderBy(c => c.Order);
        }
        /// <summary>
        /// 普通欄目樹形類表
        /// </summary>
        /// <returns></returns>
        public List<Tree> TreeGeneral()
        {
            var _root = Children(0, 0).Select(c => new Tree { id = c.CategoryId, text = c.Name, iconCls = "icon-general" }).ToList();
            if (_root != null)
            {
                for (int i = 0; i < _root.Count(); i++)
                {
                    _root[i] = RecursionTreeGeneral(_root[i]);
                }
            }
            return _root;
        }
        /// <summary>
        /// 普通欄目樹形類表遞歸函數
        /// </summary>
        /// <param name="tree"></param>
        /// <returns></returns>
        private Tree RecursionTreeGeneral(Tree tree)
        {
            var _children = Children(tree.id, 0).Select(c => new Tree { id = c.CategoryId, text = c.Name, iconCls="icon-general" }).ToList();
            if (_children != null)
            {
                
                for (int i = 0; i < _children.Count(); i++)
                {
                    _children[i] = RecursionTreeGeneral(_children[i]);
                }
                tree.children = _children;
            }
            return tree;
        }

打開CategoryController,添加一個 [JsonTreeParent()]  返回可以做父欄目的欄目樹列表。

 

#region json
        [AdminAuthorize]
        public JsonResult JsonTreeParent()
        {
            categoryRsy =new CategoryRepository();
            var _children = categoryRsy.TreeGeneral();
            if (_children == null) _children = new List<Tree>();
            _children.Insert(0, new Tree { id = 0, text = "",iconCls="icon-general" });
            return Json(_children);
        }
        #endregion

打開ManageAdd.cshtml,將@Html.EditorFor(model => model.ParentId)改為<input id="ParentId" type="text" class="easyui-combotree" data-options="url:'@Url.Action("JsonTreeParent", "Category")'" value="0" /> .

在@section Scripts中減價easyui的腳本和css引用

@section Scripts {
    @Styles.Render("~/EasyUi/icon")
    @Scripts.Render("~/bundles/EasyUi")
    @Scripts.Render("~/bundles/jqueryval")
}

OK,打開瀏覽器測試一下

image

可以正常添加欄目。

==============================

附代碼包:http://pan.baidu.com/share/link?shareid=123536&uk=2198133459

==============================

今天發現一個問題無論父欄目宣布選什么,提交的ParentId為0,上面“打開ManageAdd.cshtml,將@Html.EditorFor(model => model.ParentId)改為<input id="ParentId" type="text" class="easyui-combotree" data-options="url:'@Url.Action("JsonTreeParent", "Category")'" value="0" /> .” 這里有問題,應改為:@Html.TextBox("ParentId",0,new {@class ="easyui-combotree",data_options="url:'"+Url.Action("JsonTreeParent", "Category")+"'" })。

修改后正常了,但是使用easyui combotree后,父欄目客戶端驗證無效了,這個是什么原因,如何解決,知道的園友不吝賜教!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM