问题描述
我正在尝试创建一个常规主页,该主页取决于传递给控件的参数,将显示不同的内容(模块).
I am trying to have a general home page that depending on the parameter passed to the control, different content (modules) will be displayed.
例如,用户可以从菜单中选择"Kentucky",而"Kentucky"的ID为1.主控制器获取ID(1)并确定该模块的可能模块状态(一个简单的db调用.)也许有一个用于状态的公告模块和联系人模块.公告模块可以包含多个项目,但是它仅仅是一个模块.每种类型的模块都有局部视图.
For example, a user may select Kentucky from the menu and the id for Kentucky is 1. The home controller gets the id (1) and determines the possible modules for thatstate (a simple db call.) Perhaps there is an announcements module and a contacts module for the state. An announcements module could have several items but it's only one module. There would be a partial view for each type of module.
这是我的基本设置.
public interface IModuleRepository
{
IList<MenuItemModule> GetMenuItemModules(int menuItem);
IList<Announcements> GetAnnouncements(int modID);
IList<News> GetNews(int modID);
IList<Contacts> GetContacts(int modID);
}
//business object
public class MenuItemModule
{
private int _MenuItemID;
private int _ModuleID;
private int _ModuleDefID;
private string _Src;
private int _ModuleOrder;
//get, set properties for these...
}
//announcements entity
public class Announcements
{
private int _ID = -1;
private int _MenuItemID = -1;
private int _ModuleID = -1;
private string _Description = string.Empty;
//get set props ...
}
在我的家庭控制器中...
In my home controller...
public class HomeController : Controller
{
private IModuleRepository modRepository;
public HomeController(IModuleRepository modRepository)
{
this.modRepository = modRepository;
}
public ViewResult Item(string ItemID)
{
//returns a list of menuitemmodules for the page. This gives me the Src or name of each
//module on the page, i.e. Announcements, news, contacts, etc.
var modules = modRepository.GetMenuItemModules(Convert.ToInt32(ItemID));
return View(modules);
}
}
我尝试过几种不同的模型来返回,但是我总是遇到一些限制.如果我将menuitemmodules传递给Item.aspx,则可以执行以下操作:
I have tried several different models to return but I always run up against some contstraint. If I pass the menuitemmodules to my Item.aspx, then I can do something like this:
foreach (var mod in Model)
{
Html.RenderPartial(mod.Src, a); //needs an announcement object though
}
这使它有些动态,因为我有一个Src,它基本上类似于"Announcements",并且我可以只创建一个announcements.ascx部分来处理该模块.但是我发现很难传递我的menuitemmodule和公告实体.
That makes it somewhat dynamic because I have the Src which would basically be something like "Announcements" and I can just create an announcements.ascx partial to process the module. But I have found it difficult to pass my menuitemmodule and an announcements entity as well.
我还搞砸了传递一个更复杂的对象,然后测试通过If语句传递的每个Src.随着我增加应用程序中可能的模块数量,这将使将来的扩展变得困难.
I have also messed around with passing a more complex object and then testing every Src that comes through with an If statement. This would make scaling difficult in the future as I increase the number of possible modules in the app.
我该如何解决我的问题?我希望我提供了足够的信息.我在这里喜欢基本的想法- http://www.mikesdotnetting.com/Article/105/ASP.NET-MVC-Partial-Views-and-Strongly-Typed-Custom-ViewModels ,但这似乎仅适用于以下静态模块:页面.
How can I solve my problem? I hope I have provided enough info. I like the basic idea here - http://www.mikesdotnetting.com/Article/105/ASP.NET-MVC-Partial-Views-and-Strongly-Typed-Custom-ViewModels but that seems to only work for static modules on a page.
我确实尝试了一个名为ModuleViewModel的复合视图模型.这是尝试:
I did try a composite view model called ModuleViewModel. Here is that attempt:
public class ModuleViewModel
{
public IList<Announcements> announcements { get; set; }
public IList<MenuItemModule> mods { get; set; }
}
如果我将模型传递给Item.aspx,我可以做类似的事情(但是我做错了,因为看起来不对.)
If I pass that model to the Item.aspx I can do something like this (but I must be doing something wrong because something doesn't look right.)
foreach (var mod in Model)
{
if (mod.announcements.Count > 0)
{
Html.RenderPartial("Announcements", mod.announcements);
}
}
再一次,可扩展性将困扰我.我想在商品页面上有这样的东西:
Once again, scalability is going to haunt me. I would like to have something like this on item page:
foreach (var mod in Model)
{
Html.RenderPartial(mod.Src, mod);
}
那将是正确的局部视图,并为其传递正确的模型.
That would the correct partial view and pass it the correct model.
推荐答案
在解决了一个多星期之后,我终于设法弄清了MVC如何动态地实现我想要的功能.我决定将自己的解决方案发布给其他MVC新手.希望以下内容可以消除我的误解(尽管就我目前对MVC的理解而言,我不能说这是最好的方法.)
After messing around with this for over a week, I finally managed to figure out how MVC can do what I want dynamically. I decided to post my solution for others that are new to MVC. Hopefully, the following will clear up the misunderstandings I had (although, at this point in my understanding of MVC, I cannot say this is the best approach.)
为了清楚起见,我将包括以前的代码片段和修改内容:
I will include the previous code snips and modifications for clarity:
public interface IModuleRepository
{
IList<MenuItemModule> GetMenuItemModules(int menuItem);
IList<Announcements> GetAnnouncements(int modID);
IList<News> GetNews(int modID);
IList<Contacts> GetContacts(int modID);
}
//business object
public class MenuItemModule
{
private int _MenuItemID;
private int _ModuleID;
private int _ModuleDefID;
private string _Src;
private int _ModuleOrder;
//get, set properties for these...
}
//announcements entity
public class Announcements : MenuItemModule
{
private int _ID = -1;
private string _Description = string.Empty;
//get set props ...
}
我还添加了另一个班级:
I also added another class:
public class AnnouncementModule : MenuItemModule
{
private IList<Announcements> _Announcements;
//get set prop
}
...然后我为视图创建了一个模型
...and I created a model for the view
public class HomeItemViewModel
{
public MenuItemModule[] MenuItemModules { get; set; } //collection of menuitemmodules
}
在我的家庭控制器中...
In my home controller...
var menuItemModules = modRepository.GetMenuItemModules(ItemID);
if (menuItemModules.Count > 0)
{
AnnouncementModule aMod;
MenuItemModule[] mods = new MenuItemModule[menuItemModules.Count()];
int i = 0;
//loop through each MenuItemModule assign to the appropriate model
foreach (MenuItemModule mod in menuItemModules)
{
if (mod.Src == "Announcements")
{
aMod = new AnnouncementModule();
aMod.Announcements = modRepository.GetAnnouncements(mod.ModuleID);
//now add this to the menuitemmodule collection
mods[i] = aMod;
}
if (mod.Src == "Contacts")
{
//...
}
i++;
}
}
var viewModel = new HomeItemViewModel
{
MenuItemModules = mods
};
return View(viewModel);
然后我使用了在视图中使用DisplayFor的建议.该视图被严格键入HomeItemViewModel.
Then I used the suggestion to use DisplayFor in the view. The view is strongly typed to HomeItemViewModel.
<%: Html.DisplayFor(m => m.MenuItemModules) %>
这会遍历集合,并根据类型,将调用该模板.在此示例中,它将调用AnnouncementModule.ascx,该类型强烈地键入到AnnouncementModule.
This iterates through the collection and based on the type, it will call that template. In this example, it calls AnnouncementModule.ascx which is strongly typed to AnnouncementModule.
foreach (var a in Model.Announcements)
{
//a.Description will give us the description of the announcement
}
我意识到有多种方法可以编码控制器,并且我打算进行重构,但是这个框架应该提供解决我所发布问题的基础.
I realize there are slicker ways to code the controller, and I plan on refactoring, but this skeleton should provide the basics to solve the question I posted.
这篇关于如何在MVC中使用存储库模式创建动态的多个局部视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!