I am trying to implement a search panel with several checkbox to filter a table data, but i have a problem. I cant retain value of input checked after submit.
How can I solve?
My model :
public class OrdineView
{
public int anno { get; set; }
public Int32 nrOrdine { get; set; }
public string centro { get; set; }
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:d}")]
public DateTime? data { get; set; }
public String codice { get; set; }
public String ragsoc { get; set; }
[DisplayFormat(DataFormatString = "{0:C}")]
public Nullable<double> importo;
}
I have a Search model:
public class OrdiniSearchModel
{
public int? anno {get;set;}
public String[] Distinzione {get;set;}
}
public class OrdiniBusinessLogic
{
private NORTHWNDEntities1 db;
public OrdiniBusinessLogic()
{
db = new NORTHWNDEntities1();
}
public IQueryable<OrdineView> GetOrdini(OrdiniSearchModel ordiniSearch)
{
var queryOrdineView = (from ordine in db.ORDINI
join cliente in db.CLIENTI on ordine.Codcli equals cliente.Codana
select new OrdineView
{
anno = ordine.Anno,
nrOrdine = ordine.Numord,
centro = ordine.Codcen,
data = ordine.Datord,
codice = ordine.Codcli,
ragsoc = cliente.Ragso1,
importo = ordine.Totord
}).ToList().AsQueryable();
var model = queryOrdineView;
if (ordiniSearch.anno != null)
{
model = model.Where(o => o.anno == ordiniSearch.anno);
}
if (ordiniSearch.Distinzione != null && ordiniSearch.distinzione.Count() > 0)
{
List<string> distinzioniSelezionate = new List<string>();
foreach (var item in ordiniSearch.Distinzione)
{
distinzioniSelezionate.Add(item);
}
model = model.Where(o => distinzioniSelezionate.Contains(o.distinzione));
}
return model;
}
}
My Controller:
public ActionResult Index(OrdiniSearchModel searchModel, int? pageNumber )
{
ViewBag.Anno = db.ORDINI.Select(o => new { o.Anno }).Distinct().OrderByDescending(o => o.Anno).Select(o => o.Anno);
var searchLogic = new OrdiniBusinessLogic();
var model = searchLogic.GetOrdini(searchModel);
return View(model.OrderBy(i => i.codice).ToPagedList(pageNumber ?? 1, 10));
}
In my view I have
<input name="Distinzione" type="checkbox" value="001">001
<input name="Distinzione" type="checkbox" value="002">002
...and so on
After submit I get data correctly but lose checked state.
UPDATE: Based on the comments, I updated the view and adde more code.
If you mean that the checkboxes don't stay checked after the page is refreshed. It's because you don't tell them which should be checked. There is one possible solution for you. Create a simple helper method right in the view where you need the checkboxes. This method just checks the array of values and if it finds the value there, it will render a checkbox with checked state.
View.cshtml
#model OrdinePagedList
#MyCheckbox("001")
#MyCheckbox("002")
#helper MyCheckbox(string value)
{
if (Model.Distinzione.Contains(value))
{
<input type="checkbox" name="Distinzione" value="#value" checked="checked"/>
}
else
{
<input type="checkbox" name="Distinzione" value="#value" />
}
#value
}
I suggest to create a new view model class:
public class OrdinePagedList
{
public IEnumerable<OrdiniView> Pages { get; set; }
public IEnumerable<string> Distinzione { get; set;
}
And update either your business logic so that it returns this new class
// from
public IQueryable<OrdineView> GetOrdini(OrdiniSearchModel ordiniSearch)
// to
public OrdinePagedList GetOrdini(OrdiniSearchModel ordiniSearch)
or update the controller:
public ActionResult Index(OrdiniSearchModel searchModel, int? pageNumber )
{
ViewBag.Anno = db.ORDINI.Select(o => new { o.Anno }).Distinct().OrderByDescending(o => o.Anno).Select(o => o.Anno);
var searchLogic = new OrdiniBusinessLogic();
var pages = searchLogic.GetOrdini(searchModel);
OrdinePagedList model = new OrdiniPagedList {
Pages = pages.OrderBy(i => i.codice).ToPagedList(pageNumber ?? 1, 10),
Distinzione = searchModel.Distinzione
}
return View(model);
}
or if you don't want (or can't) create the new view model (but I strongly recommend to do so). You can use ViewBag to pass the additinal collection of checked values:
public ActionResult Index(OrdiniSearchModel searchModel, int? pageNumber)
{
ViewBag.Distinzione = searchModel.Distinzione;
// original code
}
and then you'll just have to update the helper method. For the sake of simplicity I don't check if the ViewBag.Distinzione exists. But you should.
#helper MyCheckbox(string value)
{
if (ViewBag.Distinzione.Contains(value))
{
<input type="checkbox" name="Distinzione" value="#value" checked="checked"/>
}
else
{
<input type="checkbox" name="Distinzione" value="#value" />
}
#value
}
In short. You need to make sure that the data (collection of checked values), you get in controller, are being sent back to the view.
List<string> distinzioniSelezionate = new List<string>();
if (searchModel.distinzione != null && searchModel.distinzione.Count() > 0)
{
foreach (var item in searchModel.distinzione)
{
distinzioniSelezionate.Add(item);
}
}
OrdinePagedList model = new OrdinePagedList
{
Pages = pages.OrderBy(i => i.Codice).ToPagedList(pageNumber ?? 1, 10),
Distinzione = distinzioniSelezionate
};
I had to modify the ActionResult because Distinzione is not empty
Related
Selected value is not coming when I am trying to check, drop down list is showing all the names, but when I am trying to show the selected value of the dropdownlist in the controller, option is not coming.
Controller:
public ActionResult Index1()
{
Class1 cs1 = new Class1();
return View(cs1);
}
[HttpPost]
public ActionResult Index1(Class1 cs)
{
var selecteditem = cs.psudetail.Find(p => p.Section_PSU == cs.psudetail.ToString());
if (selecteditem != null)
{
}
}
Model class:
namespace WebApplication1.Models
{
public class Class1
{
public List<PSUMaster> psudetail
{
get
{
PSUEntities pe = new PSUEntities();
return pe.PSUMasters.ToList();
}
}
}
}
And the View with Model:
#model WebApplication1.Models.Class1
#{
ViewBag.Title = "Index1";
}
<br />
#Html.DropDownListFor(m => m.psudetail, new SelectList(Model.psudetail, "S_no", "Section_PSU"), "--Select PSU--")
You need to have a property that can "store" the selection you make in the list. Extend the view model (Class1) to include a property SelectedPSU. I guess that S_no in the PSUMaster is the ID, and of type integer. Otherwise adjust the code accordingly!
I have also changed the list to be just a list, and then the controller can worry about populating it. This pattern fits MVC better (keep the model simple).
Updated class:
namespace WebApplication1.Models
{
public class PsuViewModel
{
public int SelectedPSU { get; set; }
public List<PSUMaster> PSU { get; set; }
}
}
Next, the controller has to be updated to pass the list to the view model in the GET Index method:
public ActionResult Index1()
{
var pe = new PSUEntities();
return View(new PsuViewModel {
PSU = pe.PSUMasters.ToList()
});
}
Now we can use the SelectedPSU property in our view:
#model WebApplication1.Models.Class1
#{
ViewBag.Title = "Index1";
}
<br />
#Html.DropDownListFor(m => m.SelectedPSU, new SelectList(Model.PSU, "S_no", "Section_PSU"), "--Select PSU--")
...and we can get the ID in the controller:
[HttpPost]
public ActionResult Index1(PsuViewModel model)
{
var pe = new PSUEntities();
var selectedPsu = pe.PSUMasters.FirstOrDefault(p => p.S_no == model.SelectedPSU);
if (selectedPsu != null) {
// ...
}
}
I have a Model that gets sent to a view. This model has List elements that are used to populate listboxes. In this view, I post to a controller action passing in my model as a parameter. On postback, I can see primitive types, but, can't seem to access the list. Here's my code:
Model:
public class ReportInfoViewModel
{
public int report_id { get; set; } = 0;
public string report_name { get; set; } = "";
public string report_path { get; set; } = "";
public string plaza_param { get; set; } = "y";
public List<FacilityViewModel> facilitieslist { get; set; } = new List<FacilityViewModel>();
}
public class FacilityViewModel
{
public string facility_id { get; set; }
public string facility_name { get; set; }
}
View:
#model CSC.ViewModels.ReportInfoViewModel
#using (Html.BeginForm("ViewReport", "Reports", Model, FormMethod.Post, new { target = "_blank" }))
{
if (#Model.plaza_param.ToString().ToLower().Equals("y"))
{
#Html.DevExpress().ListBox(
l =>
{
l.Name = "lstPlazaParam";
l.Width = Unit.Pixel(300);
l.Height = Unit.Pixel(120);
l.Properties.SelectionMode = ListEditSelectionMode.CheckColumn;
l.Properties.EnableSelectAll = true;
l.Properties.TextField = "facility_name";
l.Properties.ValueField = "facility_id";
l.SelectedIndex = 0;
l.Properties.ValueType = typeof(string);
l.Properties.ValidationSettings.RequiredField.IsRequired = true;
l.Properties.ValidationSettings.RequiredField.ErrorText = "Please select a Plaza";
l.Properties.ValidationSettings.ErrorText = l.Properties.ValidationSettings.RequiredField.ErrorText;
l.Properties.ValidationSettings.ErrorTextPosition = ErrorTextPosition.Bottom;
l.Properties.ValidationSettings.Display = Display.Dynamic;
l.Properties.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText;
}).BindList(Model.facilitieslist).GetHtml();
ViewContext.Writer.WriteLine("<br />");
}
Controller:
[HttpPost]
[Authorize]
public ActionResult ViewReport(ReportInfoViewModel _model)
{
string _parameterList = "";
ReportViewerViewModel _rptObj = new ReportViewerViewModel();
if (_model.plaza_param.ToLower().Equals("y"))
{
string[] _selected = DevExpress.Web.Mvc.ListBoxExtension.GetSelectedValues<string>("lstPlazaParam");
string subParam = "plazaparam=";
subParam += String.Join(",", _selected);
_parameterList = string.Concat(_parameterList, "#", subParam);
_parameterList = string.Concat(_parameterList, "#usrplazaparam=", getSelectedPlazaDisplayValues(_model.facilitieslist, _selected));**//here, _model.facilitieslist is null**
}
return View("AfterView", _rptObj);
}
What I am trying to do is on post back, send the model back to the controller. All primitive types are sent back, except the list types. How do I send back a list model on post? Any help is appreciated.
I was able to create a hidden field in my view serializing the list and storing it in the hidden field.
#using (Html.BeginForm("ViewReport", "Reports", Model, FormMethod.Post, new { target = "_blank" }))
{
string facilitiesListJson = Newtonsoft.Json.JsonConvert.SerializeObject(#Model.facilitieslist);
#Html.Hidden("FacilitiesList", facilitiesListJson);
//other form objects
}
In my controller action, I deserialized the hidden field(Request.Form) and access the list.
string _jsonString = Request.Form["FacilitiesList"];
List<FacilityViewModel> _objList = JsonConvert.DeserializeObject<List<FacilityViewModel>>(_jsonString);
How would one go about to pass a hardcoded List of Cards (a deck) from View to Controller. I've tried several different things to pass it, but with various results. My index is a screen with 52 cards where you can draw the top card, and I want to be able to shuffle them, and even add a new deck to the current deck, and update the hardcoded list.
This is some of the relevant code. Any suggestions?
EDIT: The formpost method is where I am not sure about. I could probably add just a new List of Cards in the Action, but then the issue will arise again when I try to add a new deck to the current deck.
public class Card
{
public Suit Suit { get; set; }
public Cardnumber Cardnumber { get; set; }
public Card(Cardnumber c, Suit s)
{
this.Cardnumber = c;
this.Suit = s;
}
}
DeckOfCardsViewModel.cs
public class DeckOfCardsViewModel
{
public int ID { get; set; }
public List<Card> Cards { get; set; }
}
HomeController.cs
public ActionResult Index()
{
if (deck.Count < 1)
{
deck = new Deck().NewDeck();
deckViewModel = new DeckOfCardsViewModel();
deckViewModel.ID = 1;
deckViewModel.Cards = deck;
return View(deckViewModel);
}
else return View();
}
public ActionResult ShuffleDeck(DeckOfCardsViewModel shuffledDeck)
{
shuffledDeck.Cards = shuffledDeck.Cards.OrderBy(a => Guid.NewGuid()).ToList();
deckViewModel = shuffledDeck;
return View("Index",shuffledDeck);
}
Index.cshtml
#model DeckOfCards.Models.DeckOfCardsViewModel
#using (Html.BeginForm("ShuffleDeck", "Home", ****FormMethod.Post?***))
{
#Html.HiddenFor(Model => Model.Cards);
#Html.HiddenFor(Model => Model.ID);
<button class="btn btn-primary" name="TEST" type="submit" value="Submit">Shuffle</button>
}
Here are my model classes:
public class SensorTest
{
public int SerialNo { get; set; }
public string SensorName { get; set; }
public string TestName { get; set; }
public List<string> ImpactSide { get; set; }
}
public class SensorTestsViewModel
{
public List<SensorTest> SensorTestList { get; set; }
}
Controller action methods:
GET:
[HttpGet]
public ActionResult SensorTests()
{
SensorTestsViewModel obj = new SensorTestsViewModel();
obj.SensorTestList = new List<SensorTest>();
SensorTest sensortest;
sensortest = new SensorTest();
sensortest.SerialNo = 1;
sensortest.SensorName = "FLAT 13 KMH";
sensortest.TestName = "";
obj.SensorTestList.Add(sensortest);
sensortest = new SensorTest();
sensortest.SerialNo = 1;
sensortest.SensorName = "CURB IMPACT 40KMH";
sensortest.TestName = "";
obj.SensorTestList.Add(sensortest);
return View(obj);
}
POST:
[HttpPost]
[ActionName("SensorTests")]
public ActionResult SensorTests_Post(SensorTestsViewModel sensortests)
{
//SensorTestsViewModel model = new SensorTestsViewModel();
//UpdateModel(model);
return View(sensortests);
}
View code:
#model Safety.Models.SensorTestsViewModel
#using (Html.BeginForm("SensorTests", "Safety"))
{
var grid = new WebGrid(Model.SensorTestList, canSort: false, canPage: false);
int rowNum = 0;
<div>
#grid.GetHtml(columns:
grid.Columns
(
grid.Column("SerialNo", format: item => rowNum = rowNum + 1),
grid.Column("SensorName"),
grid.Column("TestName", format: (item) => Html.TextBox("TestName[" + (rowNum - 1).ToString() + "].TestName", (object)item.TestName))
), mode: WebGridPagerModes.Numeric)
</div>
<input type="submit" value="Submit" />
}
See the Viewmodel is null during POST. I have tried UpdateModel as well. My requirement is I need to post whole viewmodel data to controller and do the necessary actions from there. Not sure what I am missing? Can someone Please suggest?
First, take a look at this example: post items of webgrid asp.net mvc3
Try making the textbox name like this: "SensorTestList[someIndexHere].SensorName"
I have two dropdown lists and two textboxes
Search By: ByHtml.DropDownList("Search1", "Please Select...")
Html.TextBox("searchString1")
Search By: Html.DropDownList("Search2", "Please Select...")
#Html.TextBox("searchString2")
<input type="submit" value="Filter" />
When I make my selection from whichever DDL and type text into the textbox and hit filter my search returns, however after the search the text remains in the textbox, is there a way of clearing it after the search so that the textbox is empty again? I tried
ModelState.Remove("");
but it didn't work.
A sample from My controller code is
public class MainController : Controller
{
private DBEntities db = new DBEntities();
// GET: /Main/
public ActionResult Index(string searchString1, string searchString2, string Search1, string Search2)
{
//Create a Dropdown list
var SearchOptionList = new List<string>();
SearchOptionList.Add("LandLord");
SearchOptionList.Add("Postcode");
SearchOptionList.Add("Street Address");
ViewBag.Search1 = new SelectList(SearchOptionList);
ViewBag.Search2 = new SelectList(SearchOptionList);
var mylist = from m in "mydatabase" select m;
//This statement runs if the user selects a parameter from Search2 and leaves Search1 empty
if (String.IsNullOrEmpty(Search1) && !String.IsNullOrEmpty(Search2))
{
if (Search2 == "Postcode")
{
mylist = mylist.Where(s => s.Postcode.Contains(searchString2));
}
if (Search2 == "LandLord")
{
mylist = mylist.Where(s => s.Name.Contains(searchString2));
}
if (Search2 == "Street Address")
{
mylist = mylist.Where(s => s.StreetAddress.Contains(searchString2));
}
}
return View(mylist.ToList());
}
Your should have a view model containing properties searchString1 and searchString2 and the select lists
public class SearchVM
{
public string searchString1 { get; set; }
public string searchString2 { get; set; }
public SelectList SearchList1 { get; set; }
public SelectList SearchList2 { get; set; }
}
Controller
public ActionResult Search()
{
SearchVM model = new SearchVM();
model.SearchList1 = new SelctList(...);
model.SearchList2 = new SelctList(...);
return View(model);
}
View
#model SearchVM
#using(Html.BeginForm())
{
....
#Html.DropDownListFor(m => m.searchString1, Model.SearchList1, "--Please select--")
#Html.DropDownListFor(m => m.searchString2, Model.SearchList2, "--Please select--")
....
}
Post
[HttpPost]
public ActionResult Search(SearchVM model)
{
// to clear all modelstate and reset values
ModelState.Clear();
model.searchString1 = null;
model.searchString2 = null;
// or to clear just one property and reset it
ModelState.Remove("searchString1");
model.searchString1 = null;
// repopulate select lists if your returning the view
return View(model);
}
At the end of my public ActionResult Index method but before return View() I placed the following code which worked perfectly
ModelState.Remove("searchString1");
ModelState.Remove("searchString2");
ModelState.Remove("Search1");
ModelState.Remove("Search2");
I know is an old question, but I fall in the same issue. So I put my solution.
View:
#Html.TextBox("Search", null, new { #autofocus = "autofocus" })
Controller:
ViewBag.Search= null;
ModelState.Remove("Search");
return View(list.ToList());
Hope to help someone