Multiple Checkboxes to select and save values in d

2019-09-15 01:58发布

问题:

The project i am working on requires me to put check boxes on a form for the user to possibly select more than one item. I could just put these as bool in individual columns but the check box values may change or need added to. So i created a table that holds the names of these check boxes and then list them out. My question is; how do i get those values into another table that coincides with the customer. How should this be handled properly?

The view has the company name and record id /AuditSchedule/details/208 I have read that it is not good practice to put more than one value in a column but what other choice do i have?

thanks much!

What i have for the table of customers is a field for ProductType. This is not linked to anything. There is another table with the Product types which i want to list out as check boxes. I do not have any relationship between these two tables. To me doesn't seem like there should be but please correct me and let me know if there is supposed to be. So when a check box is selected i want that value (ProductName) to be put in the customer table in the ProductType field separated with commas.

Here is Customer or Schedule table:

    public class AuditSchedule
{
    public virtual int AuditScheduleID { get; set; }
    public virtual Nullable<DateTime> audit_completed_date { get; set; }
    public virtual string gl_cmp_key { get; set; }
    public virtual string audit_year { get; set; }
    public virtual string ar_ship_key { get; set; }
    public virtual string ar_ship_name { get; set; }
    public virtual string im_adres_city { get; set; }
    public virtual string im_adres_state { get; set; }
    public virtual string audit_type { get; set; }
    public virtual string audit_no { get; set; }
    public virtual string audit_group { get; set; }
    public virtual string Footage { get; set; }
    public virtual string Rolling3MosFootage { get; set; }
    public virtual string snp_SalesRep8 { get; set; }
    public virtual string epg_sales_rep_accountable { get; set; }
    public virtual string tech_service_rep { get; set; }
    public virtual string audit_done_by { get; set; }
    public virtual Nullable<DateTime> audit_recieved_date { get; set; }
    public virtual string audit_notes { get; set; }
    public virtual string audit_pdf { get; set; }
    public virtual string updated { get; set; }
    public virtual string hidden { get; set; }
    public virtual string en_stats_key { get; set; }
    public virtual string Control_ID { get; set; }
    public virtual Nullable<DateTime> audit_date { get; set; }
    public virtual string contacts_present { get; set; }
    public virtual string audit_furnished_to { get; set; }
    public virtual string spacer_type { get; set; }
}

Here is the Product Table:

    public class SpacerProduct
{
    public int SpacerProductID { get; set; }
    public string SpacerBrand { get; set; }
    public string SpacerName { get; set; }
}

Hope this helps

The view is a form type edit for AuditSchedules with only a few places that get filled in. That part works. Adding the check boxes to the view is where i am lost. I created a partial view that populates a ToList of the checkboxes and then added that to the form. Not sure how to get the results in the table.

Questions for Tohid: I have question about a few things. Firstly the ViewModel I am assuming that this is just a namespace you have for your Models directory where mine is just Models. _db.getAuditScheduleById is not in my Entities which you explained that i might have to do another way. For me it would be _db.AuditSchedules it appears in the dropdown but does not like it so i changed it to be Updated 07/02/2012 viewModel.AuditScheduleInstance = _db.AuditSchedules.Single(r => r.AuditScheduleID == id);

I am still having an issue on the

_db.GetAvailableSpacerProducts()

i do not have anything in my entities that reflects that and i am not sure how to change it. Possibly something like what i changed in the other one but not sure.

Updated 07/05/2012

Here is the QQAEntities:

namespace QQAForm.Models

{
public class QQAEntities : DbContext
   {
    public DbSet<AuditSchedule> AuditSchedules { get; set; }
    public DbSet<Category> Categories { get; set; }
    public DbSet<SubCategory> SubCategories { get; set; }
    public DbSet<MainQuestion> MainQuestions { get; set; }
    public DbSet<Suggestion> Suggestions { get; set; }        
    public DbSet<DocumentLink> DocumentLinks { get; set; }
    public DbSet<Audit> Audits { get; set; }
    public DbSet<AuditData> AuditDatas { get; set; }
    public DbSet<SpacerProduct> SpacerProducts { get; set; }
    public DbSet<ScoreCard> ScoreCards { get; set; }



   }
}

I also have another project in my solution called QQAForm.Data this only controls the roles and security for everything that is involved with memberships. Hope this helps. thank you for your time and patience.

Updated 07/06/2012

Final Working Edit:

    [HttpPost]
    public ActionResult Edit(AuditScheduleEdit viewModel)
    {            
        if (ModelState.IsValid)
        {
            viewModel.PopulateCheckBoxsToSpacerType();
            _db.Entry(viewModel.AuditScheduleInstance).State = System.Data.EntityState.Modified;
            _db.SaveChanges();
            return RedirectToAction("Index");
        }
        else
        {
            return View(viewModel);
        }

    }

Updated 08/02/2012

I have decided that i can use this in other areas of this project. I have multiple places where i use checkboxes.

I tried to implement this on another view and it is not working. The reason it does not work is because in order to populate the checkboxes it lookes at an ID in the current table so it can update it. This is the snippet:

        //get
    public ActionResult _Forms(int id)
    {
        AuditFormEdit viewModel = new AuditFormEdit();
        viewModel.ScoreInstance = _db.MainAnswers.Single(r => r.MainAnswerID == id);
        viewModel.InitializeScoreCheckBoxHelperList(_db.Scores.ToList());
        return View(viewModel);
    }

    //post
    [HttpPost]
    public ActionResult _Forms(int id, AuditFormEdit viewModel)
    {
        if (ModelState.IsValid)
        {
            viewModel.PopulateCheckBoxsToScores();
            _db.Entry(viewModel.ScoreInstance).State = System.Data.EntityState.Modified;
            _db.SaveChanges();
            return RedirectToAction("/");
        }
        else
        {
            return View(viewModel);
        }
    }

The (r => r.MainAnswerID == id) is the issue. MainAnswer is the table that needs updated. The record should also insert AuditScheduleID, MainQuestionID, and text populated from the checkbox for Score. If I comment this out i get nothing to show up. What i really need is a way to take this and insert a new record with the data. Not sure how to change the code to do this.

回答1:

If I understand you correctly, you are saying:

  1. Class Customer has a string property called ProductType which hold comma-separated string of ProductType names.
  2. Class ProductType has a string property ProductName .
  3. In the View, any of ProductType s appears as a check-box and could be selected/unselected for each customer.

Correct? It looks like a many-to-many relationship to me.

Have you read this chapter of MVC tutorial: Getting Started with EF using MVC ? Especially this part: Creating a More Complex Data Model for an ASP.NET MVC Application

To me if you change type of Customer.ProductType from string to List<ProductType> it solves everything.

However, by keeping Customer.ProductType as string , it still can be solved.

Code

According to AuditSchedule and SpacerProduct classes (models), I developed a new VeiwModel class. Think of ViewModel as a container which packs other classes and makes them ready to send to the View.

namespace MvcApplication1.ViewModels
{
    public class AuditScheduleEdit
    {
        public Models.AuditSchedule AuditScheduleInstance { get; set; }

        public List<SpacerProductCheckBoxHelper> SpacerProductCheckBoxHelperList { get; set; }

        public void InitializeSpacerProductCheckBoxHelperList(List<Models.SpacerProduct> SpacerProductList)
        {
            if (this.SpacerProductCheckBoxHelperList == null)
                this.SpacerProductCheckBoxHelperList = new List<SpacerProductCheckBoxHelper>();

            if (SpacerProductList != null
                && this.AuditScheduleInstance != null)
            {
                this.SpacerProductCheckBoxHelperList.Clear();
                SpacerProductCheckBoxHelper spacerProductCheckBoxHelper;
                string spacerTypes =
                    string.IsNullOrEmpty(this.AuditScheduleInstance.spacer_type) ?
                    string.Empty : this.AuditScheduleInstance.spacer_type;
                foreach (Models.SpacerProduct spacerProduct in SpacerProductList)
                {
                    spacerProductCheckBoxHelper = new SpacerProductCheckBoxHelper(spacerProduct);
                    if (spacerTypes.Contains(spacerProduct.SpacerName))
                        spacerProductCheckBoxHelper.Checked = true;
                    this.SpacerProductCheckBoxHelperList.Add(spacerProductCheckBoxHelper);
                }
            }
        }

        public void PopulateCheckBoxsToSpacerType()
        {
            this.AuditScheduleInstance.spacer_type = string.Empty;
            var spacerTypes = this.SpacerProductCheckBoxHelperList.Where(x => x.Checked)
                                  .Select<SpacerProductCheckBoxHelper, string>(x => x.SpacerName)
                                  .AsEnumerable();
            this.AuditScheduleInstance.spacer_type = string.Join(", ", spacerTypes);
        }

        public class SpacerProductCheckBoxHelper : Models.SpacerProduct
        {
            public bool Checked { get; set; }

            public SpacerProductCheckBoxHelper() : base() { }

            public SpacerProductCheckBoxHelper(Models.SpacerProduct spacerProduct)
            {
                this.SpacerProductID = spacerProduct.SpacerProductID;
                this.SpacerName = spacerProduct.SpacerName;
                this.SpacerBrand = spacerProduct.SpacerBrand;
            }
        }
    }
}

So here's Edit methods of the related Controller:

    public ActionResult Edit(int id)
    {
        AuditScheduleEdit viewModel = new AuditScheduleEdit();
        viewModel.AuditScheduleInstance = _db.GetAuditScheduleById(id);
        viewModel.InitializeSpacerProductCheckBoxHelperList(_db.GetAvailableSpacerProducts());
        return View(viewModel);
    }

    [HttpPost]
    public ActionResult Edit(AuditScheduleEdit viewModel)
    {
        if(ModelState.IsValid)
        {
            viewModel.PopulateCheckBoxsToSpacerType();
            // TODO: Add update logic here
            return RedirectToAction("Index");
        }
        else
        {
            return View(viewModel);
        }
    }

In the first Action (HttpGET), I simply construct an instance of AuditScheduleEdit, then assign requested AuditSchedule from my database (_db.GetAuditScheduleById(id)) (You might have different way to query data from your repository).

Then a collection of SpacerProducts has to be passed to InitializeSpacerProductCheckBoxHelperList() function (sorry because long names, trying to be clear and understandable!). This function creates a list of SpacerProductCheckBoxHelper which will be used to generate check boxes on the View.

When user submits the form, AuditScheduleEdit is recreate (based on the form data) and will be sent to the second edit Action (HttpPost). There, PopulateCheckBoxsToSpacerType() convert the list of selected check boxed to a comma separated string and assign it to AuditSchedule.spacer_type

And here is the View:

@model MvcApplication1.ViewModels.AuditScheduleEdit
@using (Html.BeginForm())
{
    <div>
        <h3>Audi Schedule</h3>
        @Html.LabelFor(m => m.AuditScheduleInstance.AuditScheduleID)
        @Html.DisplayFor(m => m.AuditScheduleInstance.AuditScheduleID)
        @Html.HiddenFor(m => m.AuditScheduleInstance.AuditScheduleID)
        <br />
        @Html.LabelFor(m => m.AuditScheduleInstance.Control_ID)
        @Html.EditorFor(m => m.AuditScheduleInstance.Control_ID)
        // Here, add any field of AuditSchedule which needs to show on edit form 
        //       like what I did for AuditScheduleID and Control_ID.
        <h3>SpacerType</h3>
        @for (int index = 0; index < Model.SpacerProductCheckBoxHelperList.Count; index++)
        {
            @Html.CheckBoxFor(m => m.SpacerProductCheckBoxHelperList[index].Checked)
            @Html.LabelFor(m => m.SpacerProductCheckBoxHelperList[index], Model.SpacerProductCheckBoxHelperList[index].SpacerName)
            @Html.HiddenFor(m => m.SpacerProductCheckBoxHelperList[index].SpacerProductID)
            @Html.HiddenFor(m => m.SpacerProductCheckBoxHelperList[index].SpacerName)
            <br />
        }
    </div>
    <div>
        <input type="submit" value="Save" />
    </div>
}

I wrote this code in Visual Studio developer 2010 Exp and it works well. You can download this code from here.



回答2:

I am not clear about the problem asked by you but I assume that you require to update your record in the table(View) when the checkbox values are stored in the table created by you.I think it is not required to update your table ,you just need to create a relationship between two tables and then you can get all the date with the help of inner query and joins.

But still if you need to update your table you can use "after insert" trigger in the table created by you. It will be very helpful if you can share table structure as well.

You need to create one more table(To store relation for itemselected and the customer who is selecting it) with the columns (AuditScheduleID int,SpacerType int) this table should have composite key on both the colums and 1) column AuditScheduleID should have the foreign key relation with Customer table 2) column SpacerType shoul have the foreign key relation with Product table. 3)when customer select multiple products and submit then the information for each product & AuditScheduleID should be saved as different rows in the table created above.

Now you can store the data in this way with full normalization