65.9K
CodeProject 正在变化。 阅读更多。
Home

MVC 中的 Widget

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (20投票s)

2013年6月3日

CPOL

3分钟阅读

viewsIcon

86566

downloadIcon

2924

使用 Razor View 在 MVC 中轻松构建 Widget

引言

本文将帮助您使用 Razor 视图和 MVC4 构建一个可管理的 widget。 这不是一篇完全技术性的文章,它将为您提供在为我们的产品构建自定义组件或功能时,关于架构设计重要性的清晰概念。 在这里,我将向您展示嵌套部分视图的使用,该视图依赖于抽象,并且还具有可扩展性功能。

使用代码 

Widgets 对我们来说非常熟悉。 大多数网站都具有此功能。 对于用户来说,在一个视图中获取信息非常重要,这样他/她就可以在登录网站时非常轻松地计划他们的工作。 因此,widgets 可以包含来自多个来源的信息。 假设您的公司让您负责设计一个可以轻松插入模型并且也是动态的 widget 模块。 在这里,我将讨论关于此类需求的设计概念。 假设我们正在构建一个公告板 widget。 在这里,我正在使用接口来构建该 widget。 我在此设计中有两个主要接口

  1. IWidget.cs
  2. ISubWidget.cs

您可能会问为什么需要两个接口,IWidget 不够吗?

答案:这是因为我们需要一个动态 widget。

在这里查看详细信息

public interface ISubWidget
{
    string Topic { get; set; }
    string Description { get; set; }
} 

public  interface IWidget
{
    int SortOrder { get; set; }
    string ClassName { get; set; }
    string FooterText { get; set; }
    string HeaderText { get; set; }
    ISubWidget SubWidget { get; set; }
}  

所以这里 IWidget 有一个属性 SubWidget,它的返回类型是 ISubwidget。 现在我们的 IWidget 就像一个包一样为我们工作。 那么我们的任务是构建一个公告板 Widget,对吧?

public class NoticeBoard : IWidget
{
    public int SortOrder { get; set; }
    public string ClassName { get; set; }    
    public string FooterText { get; set; }    
    public string HeaderText { get; set; }    
    public ISubWidget SubWidget { get; set; }        
}

public class SubWidget : ISubWidget
{
    public string Topic { get; set; }        
    public string Description { get; set; }
    
}

图 1.1:具体 widget 的依赖结构

我们在类中构建了 widget,现在我们需要将其附加到 MVC 应用程序。 在展示模型填充之前,我想向您展示视图的设计概念。 我们将在这里使用部分视图。 由于接口,我们有相同的部分视图

  1. _Widget.cshtml
  2. _SubWiget.cshtml  

_Widget.cshtml 的 Razor 视图将填充 IWidget 模型,并将 ISubwidget 加载到其主体部分。 对于它们两个,路径都是 View/Shared/Widget/

@model  MvcWidgetBuilder.Models.IWidget
 
<div class="widget">
    <div class="@Model.ClassName">
 
        <div class="header">
            @Model.HeaderText
        </div>
        <div class="body">
 
            @Html.Partial(string.Concat(new[] { "Widget", 
              "/", "_SubWidget" }), @Model.SubWidget)
 
        </div>
        <div class="footer">
            @Model.FooterText
        </div>
    </div>
</div>

_SubWidget.cshtml 的 Razor 视图将填充 ISubWidget 模型

@model  MvcWidgetBuilder.Models.ISubWidget
<div class="body">
    <div>
        <div style="float: left">
            @Html.LabelFor(p => p.Topic, @Model.Topic)
        </div>
    </div>
    <div style="clear: both">
        @Model.Description
    </div>
</div>

所以我们构建了我们的部分视图。 谁将调用它们来将它们加载到浏览器中? 我们还有另一个视图来完成这项工作

  • _WidgetContainer.cshtml

我将只把模型 IWidget 传递给部分视图 _Widget.cshtml。 此视图的路径与之前相同:View/Shared/Widget/

@model  MvcWidgetBuilder.Models.IWidget
 
@foreach (MvcWidgetBuilder.Models.IWidget wm in ViewBag.Widgets)
{
    
    @Html.Partial(string.Concat(new[] { "Widget", "/", "_Widget" }), wm)
}

图 1.2:部分视图的图形图片

所以我们有三个部分视图。 现在我们将引入一个公告板的视图。

  • NoticeBoard.cshtml(路径:View/NoticeBoard/
  • 它调用了 widgetcontainer
@{
    ViewBag.Title = "Widget";
}
 
@Styles.Render("~/Style/Widget.css")
<h2>Widget</h2>
 
<p>
    @{
        
        @Html.Partial("Widget/_WidgetContainer");
    }
</p>

并且 NoticeBoard 的控制器是 NoticeBoardController。 控制器的代码是

public class NoticeBoardController : Controller
{
    //
    // GET: /Widget/

    public ActionResult Index()
    {
            return View();
    }

    public ActionResult MyNoticeBoard()
    {
        ViewBag.Widgets = GetWidgetData();
        return View();
    }

当我调用 /NoticeBoard/MyNoticeBoard 时,它只通过调用以下函数来填充 ViewBag.Widgets

public List<IWidget> GetWidgetData()
{
    var noticeboardWidget = new List<IWidget>
    {
        new NoticeBoard()
        {
         SortOrder = 1, ClassName = "high", 
           HeaderText = "Notice Board", FooterText = "" ,
         SubWidget = new SubWidget { Topic = "Office Time", 
           Description = "Office time will be change next month" },
        },
        new NoticeBoard()
        {
        SortOrder = 4, ClassName = "medium", 
          HeaderText = "Notice Board", FooterText = "" ,
        SubWidget = new SubWidget { Topic = "Salary", 
          Description = "Salary is dusburst plese check your account" },
        },
        new NoticeBoard()
        {
         SortOrder = 8, ClassName = "low", 
           HeaderText = "Notice Board", FooterText = "" ,
         SubWidget = new SubWidget { Topic = "About Lunch", 
           Description = "We need the feed back from you about the luch" },
        },              
        new NoticeBoard()
        {
         SortOrder = 2, ClassName = "high", 
           HeaderText = "Notice Board", FooterText = "" ,
         SubWidget = new SubWidget { Topic = "Emergency Meeting", 
           Description = "All  the managers please come to our meeting room by 11.30" },
        },
        new NoticeBoard()
        {
         SortOrder = 5, ClassName = "medium", 
           HeaderText = "Notice Board", FooterText = "" ,
         SubWidget = new SubWidget { Topic = "Office Meetting", 
           Description = "Todays meeting is cancel" },
        },
        new NoticeBoard()
        {
         SortOrder = 7, ClassName = "low", HeaderText = "Notice Board", FooterText = "" ,
         SubWidget = new SubWidget { Topic = "HoliDay Notice", 
           Description = "We shifted our holiday leave for 1 day" },
        },              
        new NoticeBoard()
        {
         SortOrder = 3, ClassName = "high", HeaderText = "Notice Board", FooterText = "" ,
         SubWidget = new SubWidget { Topic = "Vacancy", 
           Description = "We need a sound asp.net developer with C#" },
        },
        new NoticeBoard()
        {
         SortOrder = 6, ClassName = "medium", HeaderText = "Notice Board", FooterText = "" ,
         SubWidget = new SubWidget { Topic = "HR Notice", 
           Description = "Visiting cards proof send to you mail please check" },
        },
    };
 
    return noticeboardWidget;
}

在浏览器中,您将看到以下屏幕

但是,如果您只是更改排序顺序的返回,它就会重新排列。

return noticeboardWidget.OrderBy(p=>p.SortOrder).ToList()

关注点

在这里,我的关注点不是向您展示 CSS 或带有部分视图的 MVC Razor。 我只是尝试关注动态 Widgets 设计。 由于我们也可以传递类名,我们可以通过模型控制 CSS 或视图。 我们的 widget 视图(部分视图)不依赖于模型(公告板),而是依赖于抽象 (IWidget)。 因此,如果我们的公司想要对模型进行分类,例如 HRNotice、SalesNotice、EmployeeNotice,我们可以通过实现 IWidget 轻松地做到这一点。 那些初学者可以很容易地感受到接口的重要性,因为我很多次看到人们甚至无法回答一个简单的问题“为什么我们需要接口?” 我希望他们从这篇文章中找到基本的答案。

另一点可能出现在您的脑海中:如果我想构建一个与 _Widget_SubWidget 不同的 widget 怎么办? 我们的 IWidget 支持吗?

答案:不支持,但是如果我们要使其更具动态性,我们可以通过传递视图名称来轻松实现。

public interface ISubWidget
{
    string Topic { get; set; }
    string Description { get; set; }
    string WidgetName { get; set; } <---------------
}

public  interface IWidget
{
    int SortOrder { get; set; }
    string ClassName { get; set; }
    string FooterText { get; set; }
    string HeaderText { get; set; }
    string WidgetName { get; set; } <-------
    ISubWidget SubWidget { get; set; }
}

更改我们的视图以及在 _WidgetContainer 上加载动态视图。

@model  MvcWidgetBuilder.Models.IWidget
 
@foreach (MvcWidgetBuilder.Models.IWidget wm in ViewBag.Widgets)
{
    
    @Html.Partial(string.Concat(new[] { "Widget", "/", wm.WidgetName }), wm)
}

以下代码用于我们的动态 widget:

@model  MvcWidgetBuilder.Models.IWidget
 
<div class="widget">
    <div class="@Model.ClassName">
 
        <div class="header">
            @Model.HeaderText
        </div>
        <div class="body">
 
            @Html.Partial(string.Concat(new[] { "Widget", "/", 
              @Model.SubWidget.WidgetName }), @Model.SubWidget)
 
        </div>
        <div class="footer">
            @Model.FooterText
        </div>
    </div>
</div>

您是否注意到我们设计结构的简单变化使我们的模型更具动态性。 这只有在我的模块依赖于抽象而不是具体类型时才有可能。

© . All rights reserved.