使用模型创建视图并列出<model>

时间:2016-02-09 16:36:50

标签: asp.net-mvc entity-framework

我有一个项目模型和一个技术模型。一个项目中可以有多种技术。将有大约5-10的技术对象数量有限,将用于无限量的项目。我想把技术项目保存在枚举中或者只是作为常量变量,但我希望能够在路上添加或编辑,所以我想我会将它们放在一个表格中。

在处理列表时,我倾向于挂断电话。我希望能够创建一个项目,并在同一视图中选中项目中使用的技术的复选框(例如HTML5或CSS3)。我无法获得要在视图中显示的技术列表,以便我将其标记为已检查特定项目。

项目类:

public class Project
{
    public int Id { get; set; }
    public string Website { get; set; }
    public List<Technology> Technologies { get; set; }        
}

技术类:

public class Technology
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsActive { get; set; }
}

视图模型:

public class ProjectTechnologyViewModel
{
    public IEnumerable<Technology> Technologies { get; set; } 
    public Project Projects { get; set; }

    public ProjectTechnologyViewModel()
    {
        Projects = new Project();
    }
}

的DbContext:

public class NovaDB : DbContext
{
    public NovaDB(): base("DefaultConnection")
    {

    }

    public DbSet<Technology> Technologies { get; set; }
    public DbSet<Project> Projects{ get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }

}

控制器:

public ActionResult CreateProject()
{

    return View();
}

[HttpPost]
public ActionResult CreateProject(ProjectTechnologyViewModel viewModel)
{
    var proj = new Project();
    if (ModelState.IsValid)
    {                
        proj.LaunchDate = viewModel.Projects.LaunchDate;
        proj.ProjectType = viewModel.Projects.ProjectType;
        proj.ServiceId = viewModel.Projects.ServiceId;
        proj.ShowInOurWork = viewModel.Projects.ShowInOurWork;
        proj.Website = proj.Website;

        proj.Technologies = new List<Technology>();

        foreach (var t in viewModel.Technologies)
        {
            proj.Technologies.Add(new Technology()
            {
                Name = t.Name,
                FAClassName = t.FAClassName,
                IsActive = t.IsActive,
            });
        }

        _db.Projects.AddOrUpdate(proj);
        _db.SaveChanges();
    }

    return View(proj);
}

查看:

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Project</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        <div class="form-group">
            @Html.LabelFor(model => model.Projects.Website, htmlAttributes: new {@class = "control-label col-md-2"})
            <div class="col-md-10">
                @Html.EditorFor(model => model.Projects.Website, new {htmlAttributes = new {@class = "form-control"}})
                @Html.ValidationMessageFor(model => model.Projects.Website, "", new {@class = "text-danger"})
            </div>
        </div>

        @for (int i = 0; i < Model.Technologies.Count(); i++)
        {
            @Html.CheckBoxFor(x=>x.Technologies[i].)
        }

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

观点图片 I cannot access the Technology properties such as isActive or name

4 个答案:

答案 0 :(得分:1)

该复选框适用于技术的var promises = []; promises.push(myFuncAsync1().then(r => {name : "func1", result : r})); promises.push(myFuncAsync1().then(r => {name : "func2", result : r})); Promise.all(promises).then(results => { var lookup = results.reduce((prev, curr) => { prev[curr.name] = curr.result; return prev; }, {}); var firstResult = lookup["func1"]; var secondResult = lookup["func2"]; } 属性,对吧?所以,你可以这样做:

IsActive

您还需要实例化ViewModel并将其发送到GET操作中的视图,如下所示:

@Html.CheckBoxFor(model => model.Technologies.ToList()[i].IsActive) @Model.Technologies.ToList()[i].Name

此外,不要在ViewModel中实例化属性。在你的控制器中做到这一点(见上文):

public ActionResult CreateProject()
{
    var model = new ProjectTechnologyViewModel();
    model.Project = new Project();
    model.Technologies = new List<Technology>();

    return View(model);
}

答案 1 :(得分:0)

为什么你将IEnumerable称为数组? 这个 - someIEnumerable[0]将不会被编译 你为什么不用foreach?

foreach(var i in Model.Technologies){
   var a =  i.Website;
}

答案 2 :(得分:0)

首先,您需要一个表来存储与项目相关联的技术(例如ProjectTechnlogies),其中包括项目ID字段和技术ID字段的FK字段

然后,您需要使用视图模型来表示您希望在视图中编辑的内容

public class TechnologyVM
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsSelected { get; set; } // for binding to a checkbox
}
public class ProjectVM
{
    public string Website { get; set; }
    public IEnumerable<TechnologyVM> Technologies { get; set; }
}

,你的GET方法将是

public ActionResult Create()
{
    ProjectVM model = new ProjectVM
    {
        Technologies = _db.Technologies.Where(t => t.IsActive).Select(t => new TechnologyVM
        {
            Id = t.Id,
            Name = t.Name
        })
    };
    return View(model);
}

注意我在这里假设您的IsActive属性意味着如果值为false,则它现在是一种过时的技术(它可能已分配给以前的项目)并且您不会希望在创建新项目时允许在视图中选择。

然后在EditorTemplate中为TechnologyVM创建/Views/Shared/EditorTemplates/TechnologyVM.cshtml(部分)(请注意,文件名必须与班级名称相匹配)

@model TechnologyVM
<div>
    @Html.HiddenFor(m => m.Id)
    @Html.HiddenFor(m => m.Name) // if you want this value to be posted
    @Html.CheckBoxFor(m => m.IsSelected)
    @Html.LabelFor(m => m.IsSelected, Model.Name)
</div>

,主视图将是

@model ProjectVM
....
@using (Html.BeginForm())
{
    ....
    @Html.TextBoxFor(m => m.Website)
    ....
    @Html.EditorFor(m => m.Technologies)
    <input type="submit" ... />
}

EditorFor()方法将正确生成每个技术的html

最后你的POST方法将是

[HttpPost]
public ActionResult Create(ProjectVM model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }
    Project project = new Project
    {
        Website = model.Website,
        // ... other properties of Project
    }
    _db.Projects.Add(project);
    _db.SaveChanges(); // The Project's Id property has now been set
    IEnumerable<int> selectedTechnologies = model.Where(t => t.IsSelected).Select(t => t.Id);
    foreach(int ID in selectedTechnologies)
    {
        ProjectTechnology technology = new ProjectTechnology
        { 
          ProjectId = project.Id,
          Technology = ID
        };
        _db.ProjectTechnologies.Add(technology);
    }
    _db.SaveChanges(); // save the project technologies
    // redirect
}

答案 3 :(得分:-1)

我不得不改变一些模型,我添加了一张表来映射这两个模型。我决定保存&#34;链接&#34;项目与项目之间共享表中的技术模型称为ProjectTechnologyMap。对于我创建的项目,我插入了包含项目ID和技术ID的记录。项目ID保持不变,并且有多个技术ID,具体取决于视图中选择的数量。我还将项目详细信息保存到项目表中。我不保存任何技术表,因为它是静态的(我没有在我的创建项目视图上创建技术)。

这是我的解决方案:

<强>型号:

public class Project
{
    public int Id { get; set; }
    public string Website { get; set; }
}

public class Technology
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsActive { get; set; }
}

public class ProjectTechnologyMap
{
    public int  Id { get; set; }
    public int ProjectId { get; set; }
    public int TechnologyId { get; set; }
}

<强>视图模型:

public class ProjectTechnologyViewModel
{
    public List<Technology> Technologies { get; set; } 
    public Project Projects { get; set; }
    public ProjectTechnologyMap ProjectTechnologyMapping { get; set; }

    public ProjectTechnologyViewModel()
    {
        Projects = new Project();
        ProjectTechnologyMapping = new ProjectTechnologyMap();

    }
}

数据库上下文:

public class NovaDB : DbContext
{
    public NovaDB(): base("DefaultConnection")
    {

    }

    public DbSet<Technology> Technologies { get; set; }
    public DbSet<Project> Projects { get; set; }
    public DbSet<ProjectTechnologyMap> ProjectTechnologyMappings { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

<强>控制器:

public ActionResult Create()
        {
            var technologies = from t in _db.Technologies
                               orderby t.Name
                               where t.IsActive
                               select t;

            var viewModel = new ProjectTechnologyViewModel();
            viewModel.Technologies = technologies.ToList();

            return View(viewModel);
        }

        [HttpPost]
        public ActionResult Create(ProjectTechnologyViewModel viewModel)
        {            
            if (ModelState.IsValid)
            {
                var proj = new Project
                {
                    LaunchDate = viewModel.Projects.LaunchDate,
                    ProjectType = viewModel.Projects.ProjectType,
                    ServiceId = viewModel.Projects.ServiceId,
                    ShowInOurWork = viewModel.Projects.ShowInOurWork,
                    Website = viewModel.Projects.Website
                };

                _db.Projects.AddOrUpdate(proj);
                _db.SaveChanges();

                var map = new ProjectTechnologyMap();

                foreach (var item in viewModel.Technologies)
                {
                    if (item.UsedInProject)
                    {
                        map.TechnologyId = item.Id;
                        map.ProjectId = proj.Id;
                        _db.ProjectTechnologyMappings.Add(map);
                        _db.SaveChanges();
                    }
                }
            }

            return RedirectToAction("Index", "Project");
        }

在我的视图中循环以处理技术列表:

@for (var i = 0; i < Model.Technologies.Count; i++)
{
    <div class="form-group">
        @Html.LabelFor(x => x.Technologies[i].Name, Model.Technologies[i].Name, new {@class = "control-label col-md-2"})
        <div class="col-md-10">
            <div class="checkbox">
                @Html.EditorFor(x => x.Technologies[i].UsedInProject)
                @Html.HiddenFor(x => x.Technologies[i].Id)
            </div>
        </div>
    </div>
}