2011-03-18 15 views
10

En la maquinilla de afeitar, al cargar una vista parcial, es posible que sólo tiene que especificar el nombre de vista parcial, y el motor de vistas Razor buscará en el RazorViewEngine.PartialViewLocationFormats:¿Es posible especificar formatos de ubicación con capacidad de búsqueda para un diseño MVC Razor?

@Html.RenderPartial("_PartialView", Model); 

en realidad buscar en los lugares especificados en PartialViewLocationFormats en el motor de vista, como por ejemplo

~/Views/Home/_PartialView.cshtml 
~/Views/Shared/_PartialView.cshtml 

Sin embargo, cuando se especifica la disposición, que parecen ser obligado a especificar una ruta específica para el diseño:

@Layout = "~/Views/Shared/MyLayout.cshtml"; 

Lo que me gustaría hacer sería especificar el diseño sólo por su nombre, y tienen el la disposición real puede encontrar buscando en una lista de lugares comunes:

@Layout = "MyLayout"; 

... pero no puedo' t encuentra instalaciones para hacerlo. Como no pude encontrar ninguna documentación al respecto, intenté jugar con la configuración de RazorViewEngine.MasterLocationFormats, pero esta propiedad no se usa al ubicar diseños.

¿Alguien sabe cómo hacer esto?

Respuesta

10

Recientemente tuve problemas con un problema similar en el que, en una aplicación temática que utiliza un ViewEngine personalizado para buscar primero la ubicación del tema para las vistas, estaba intentando anular algunos archivos maestros. Una forma de forzar a la ubicación de la disposición que pasar por FindView del ViewEngine es especificar el nombre de la vista principal en una acción del controlador al volver:

return View("myView", "myViewMaster"); 

Sin embargo, si "myViewMaster" también tiene un diseño (anidado diseños), este método no funciona para el diseño anidado. Mi mejor solución hasta ahora es llamar a la vista del motor directamente en la vista:

@{ 
    Layout = (ViewEngines.Engines.FindView(this.ViewContext.Controller.ControllerContext, "myViewMaster", "").View as RazorView).ViewPath; 
} 

Esto funciona, pero sin duda podría ser encapsulado en un método de extensión para evitar la repetición y el resumen del código.

Espero que ayude!

+0

Gracias, esto funcionó para mí.Aunque, ha pasado un año, ¿alguien ha encontrado una mejor solución que me permita decir Layout = "Main2Col.cshmtl" en lugar de necesitar toda esa línea de código? – happyfirst

+2

Cree su propia clase WebViewPage -derivada y haga que todas sus vistas hereden de ella. En él, anula el diseño y en el ejecutar el código anterior. http://odetocode.com/Blogs/scott/archive/2011/01/09/razor-tip-2-inheritance-amp-configuration.aspx – sowee15

0

Intenté un par de cosas diferentes y no pude encontrar una manera de hacer lo que quería. Sin embargo, puede dejar el Diseño en blanco y usar el archivo _ViewStart.cshtml para asignar el diseño de cada página usando una propiedad ViewBag.

Por lo tanto, si tiene una enumeración (por ejemplo) y establece la propiedad viewbag dinámica de CustomLayout en un valor de esa enumeración, puede usar el archivo _ViewStart para hacer algo como esto.

@{ 
    MvcApplication12.Controllers.CustomLayouts customLayout = this.ViewContext.Controller.ViewBag.CustomLayout; 

    switch (customLayout) 
    { 
     case MvcApplication12.Controllers.CustomLayouts.Blue: Layout = "~/Views/Shared/Blue.cshtml"; break; 
     case MvcApplication12.Controllers.CustomLayouts.Green: Layout = "~/Views/Shared/Green.cshtml"; break; 
     case MvcApplication12.Controllers.CustomLayouts.Default: 
     default: Layout = "~/Views/Shared/Default.cshtml"; break; 
    } 
} 

No estoy seguro de si esto ayuda o no.

0

Tomé la respuesta aceptada de @ sowee15 y añade un método de extensión para ayudar a envolver, en un poco:

using System; 
using System.Web.Mvc; 

namespace MyApp.Classes 
{ 
    public static class ViewEngineCollectionExtensions 
    { 
     public static string FindViewPath(this ViewEngineCollection viewEngines, ControllerContext controllerContext, string viewName, string masterName = null) 
     { 
      var viewResult = ViewEngines.Engines.FindView(controllerContext, viewName, masterName ?? string.Empty); 
      if(viewResult == null) 
       throw new Exception(string.Format("The specified view {0} could not be found.", viewName)); 

      var view = viewResult.View as RazorView; 
      if(viewResult == null) 
       throw new Exception(string.Format("The specified view {0} must be a Razor view.", viewName)); 

      return view.ViewPath; 
     } 
    } 
} 

A continuación, puede llamar a la extensión de su vista o viewstart.cshtml así:

@{ 
    Layout = ViewEngines.Engines.FindViewPath(ViewContext.Controller.ControllerContext, "_PopupLayout"); 
} 
Cuestiones relacionadas