Devexpress 12.1 MVC GridView Inside Tab Strip Issues - c#

I'm an intern that has never done any web development just so you know where I'm coming from. I'm currently trying to learn asp.NET MVC 3 using devexpress 12.1 tools. I started with a template that had a devexpress gridview in the content area that is linked up to the Northwind db. It works by itself, but when I create a devexpress tab strip and place the gridview inside the second tab I get the column headings, but no data is displayed. When I click on a column heading to sort the data shows up. I'm wanting the gridview to load after I click the tab and not when the page loads. Maybe my callbacks are the problem. My tab strip is using an ajax callback and the gridview is as well for the paging. I have added the model to the TabControlPartial page and passed in the model in the controller for the TabControlPartial action. I've tried looking at the demos at mvc.devexpress.com, but there is nothing that puts the two together. I don't 100% understand passing the model into the view I guess. I know this is simple, but I don't know what to do. Thanks for your help.
Controller (this may be my issue):
public ActionResult LookUp()
{
return View(NorthwindDataProvider.GetCustomers());
}
public ActionResult _TabControlPartial()
{
return PartialView("_TabControlPartial", NorthwindDataProvider.GetCustomers());
}
public ActionResult _GridViewPartial()
{
return PartialView("_GridViewPartial", NorthwindDataProvider.GetCustomers());
}
LookUp View (Index):
#model System.Collections.IEnumerable
#Html.Partial("_TabControlPartial", Model)
Tab Partial:
#model System.Collections.IEnumerable
#Html.DevExpress().PageControl(
settings =>
{
settings.Name = "TabControl";
settings.Width = System.Web.UI.WebControls.Unit.Percentage(100);
settings.Height = System.Web.UI.WebControls.Unit.Percentage(100);
settings.CallbackRouteValues = new { Controller = "Customers", Action =
"_TabControlPartial" };
settings.TabPages.Add(
tabOne =>
{
tabOne.Name = "TabOne";
tabOne.Text = "Start";
tabOne.SetContent(() =>
{
ViewContext.Writer.Write("Start");
});
});
settings.TabPages.Add(
tabTwo =>
{
tabTwo.Name = "TabTwo";
tabTwo.Text = "Customer List";
tabTwo.SetContent(() =>
{
Html.RenderPartial("_GridViewPartial", Model);
});
});
}).GetHtml()
GridView Partial:
#Html.DevExpress().GridView(
settings =>
{
settings.Name = "GridView";
settings.CallbackRouteValues = new { Controller = "Customers", Action =
"_GridViewPartial" };
settings.Width = System.Web.UI.WebControls.Unit.Percentage(100);
settings.Height = System.Web.UI.WebControls.Unit.Percentage(100);
settings.SettingsPager.Visible = true;
settings.SettingsPager.PageSize = 15;
settings.ControlStyle.Paddings.Padding = System.Web.UI.WebControls.Unit.Pixel(0);
settings.ControlStyle.Border.BorderWidth = System.Web.UI.WebControls.Unit.Pixel(0);
settings.ControlStyle.BorderBottom.BorderWidth =
System.Web.UI.WebControls.Unit.Pixel(1);
//Configure grid's columns in accordance with data model fields
settings.Columns.Add("ContactName");
settings.Columns.Add("Address");
settings.Columns.Add("City");
settings.Columns.Add("PostalCode");
settings.Columns.Add("Phone");
}).Bind(Model).GetHtml()

You're missing the data in the GridView when the tab is opened. When you open the page, the data for the GridView needs to be loaded in the Model that is returned. right now you load the page (in LookUp), but you aren't pushing the data for the grid. whenever any callback occurs, only at that point is the data getting pulled from the database and returned to the screen (notice you only return data in the Callback methods _TabControlPartial and _GridViewPartial). When you sort a column, or filter, etc, then the callback is fired and the data is returned from the server.
The code you have looks correct, but somewhere in the process the Model is losing it's value. the best option is to put a breakpoint in the tab control, the Grid Binding, and the controller and make sure the data you expect is in place when it's bound.
You could "cheat" by putting in a callback when the tab is activated such as:
#Html.DevExpress().PageControl(
settings =>
{
settings.Name = "TabControl";
settings.ClientSideEvents.Init = "TabControl_Init";
...
}).GetHtml()
and in JavaScript have:
function TabControl_Init(s, e) {
GridView.PerformCallback();
}
this way, after the tabs are initialized, the GridView will run a callback, and grab the data correctly. But it would be better to figure out why the data isn't being sent down in the first place by stepping through the code.

Related

Switching between two partial views in a layout

I have two partial views that I want to load after clicking a button. It should work like this - the first partial view is the one that displays defaultly, after I click the button - the partial view switches to the second one. Once you click again on the same button in the partial view - the layout switches to the first one. I don't really know how to approach that problem - I thought about declaring a flag that would go from 0 to 1, but I couldn't figure out how to save that flag in a controller or in a .cshtml page so that it saves even if I refresh the page. The two partial views show in every page of my app - it's a sidebar.
Code snippet of my _layout.cshtml
<div class="container-fluid">
<div class="row">
#{
int flag = Convert.ToInt32(HttpContext.Current.Request.RequestContext.RouteData.Values["Controller"]);
if (flag == 1)
{
Html.Action("LoadPartial", "Home");
}
else
{
Html.Action("LoadPartial2", "Home");
}
}
}
</div>
</div>
Controller snippet
public PartialViewResult LoadPartial()
{
var context = new ApplicationDbContext();
var userStore = new UserStore<ApplicationUser>(context);
var userManager = new UserManager<ApplicationUser>(userStore);
var user2 = userManager.FindById(User.Identity.GetUserId());
AspNetUser model = new AspNetUser();
model.Email = user2.Email;
model.Id = user2.Id;
model.UserName = user2.UserName;
model.PhoneNumber = user2.PhoneNumber;
return PartialView("_ProfileEditPartial", model);
}
You could try saving the flag as a session value, the following link shows Mircosoft's documentation on how to set up session state: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-3.1#session-state. Once set up, you can easily set/get your value using
HttpContext.Session.SetInt32("SessionPartial", 0);
HttpContext.Session.GetStringInt32("SessionPartial");
and it stays persistent even if user refreshes. Since you said the partials show up on every page of the app, set the session variable in the first controller method your app goes into, or as early as possible.
After setting up the session variable, create a controller method which determines what partial to return based on the session value.
public PartialViewResult LoadPartial()
{
var flag = HttpContext.Session.GetInt32("SessionPartial");
if (flag == 0) {
// set up model here
return PartialView("_Partial1", model);
}
else {
// set up model here
return PartialView("_Partial2", model);
}
}
Finally, in the view write some JavaScript in which you simply get and display the partial. On the click of the button, get the div in which your partial is stored, empty it of the past partial, and then load the correct partial by calling the controller method.
$(document).ready(function() {
$("#buttonId").click(function () {
$('#divId').empty();
$('#divId').load('#Url.Action("LoadPartial", "<YourControllerNameHere>"));
});
}

Trigger button click after view got loaded

In my old MVC application, I have a login button once the application main page got loaded I have to explicitly click on login to get into the application. Now I would like to trigger the login_btn click event after my view got loaded via code.
In Jquery called the login_btn trigger event in document.ready function, and in controller I used viewBag option. Which is the best way to achieve
In jquery,
$(document).ready(function () {
$('#login_btn').trigger('click');
});
Its getting called when the page get refreshed.
In controller viewBag
public IActionResult Index(string info)
{
loginModel myModel = new loginModel();
test(); //tried
return View(myModel);
}
public void test()
{
ViewBag.JavaScriptFunction = "login()";
}
gives error login not defined, because before loading the model I am calling the test()
Provide me some info on how to trigger the login automatically after the view page got loaded.
Modifying my original answer, the solution using a flag to control the auto-login would be:
if( alreadyLoggedFlag === false ) {
alreadyLoggedFlag = true;
$('#login_btn').trigger('click');
}

Navigate between nested View Controllers across a TabBarController - Xamarin iOS

I'm having trouble with navigation outside of the typical use cases for navigation controllers and tabbar controllers. Here's a drawing of a simplified version. (real version has a TabBarController that feeds into 9 NavControllers)
In my Home Nav Controller, there's a table view where the user could select a row and that should navigate them to a particular Events Detail View Controller. At that point, the user should be able to navigate back to the Events TableView Controller to see the list of events or use the TabBar to navigate to another section.
So far with my code I can push the correct detail view controller and select the correct index of the tabbar but it only works the first time:
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
tableView.DeselectRow(indexPath, true);
var eventsDetailView = new EventsDetailController(eventPosts[indexPath.Row]);
//loop through ViewControllers array in case the user has set a custom tabbar order via the More Tab
foreach (UIViewController viewC in tbController.ViewControllers)
{
UINavigationController navController = viewC as UINavigationController;
if (navController.TabBarItem.Tag.Equals(9))
{
navController.PushViewController(eventsDetailView, false);
tbController.SelectedIndex = 9;
}
}
}
After the user has navigated to the events detail view controller, if they then:
travel to the Home ViewController via the TabBar
select a new TableRow to navigate to a different Events detail view controller
... then the same previous events detail view shows up. It doesn't matter which row the user selects in the Home View Controller. The initial detail view controller will always be the same one to be presented.
Any help pointing me in the right direction would be greatly appreciated!
Solution:
In my understanding, what you want is :
HomePageController --> EventDetailPage --> EvevtTableViewControll
So in the first step, you could push to EventDetailPage in HomePageController:
this.NavigationController.PushViewController(new HomeDetailUIViewController(), true);
Then, in your EventDetailPage, you can customize a back button, for example:
UIBarButtonItem backBtn = new UIBarButtonItem();
backBtn.Title = "back";
backBtn.Style = UIBarButtonItemStyle.Plain;
this.NavigationItem.LeftBarButtonItem = backBtn;
backBtn.Clicked += (sender, e) =>
{
// 1 here is an example, it should be the index of your EvevtTableViewControll
NavigationController.TabBarController.SelectedIndex = 1;
NavigationController.PopToRootViewController(true);
};
Set the NavigationController.TabBarController.SelectedIndex=1 first to make sure EvevtTableViewControll will show after you back from EvevtDetailViewControll, then your PopToRootViewController to back to the EvevtTableViewControll.
Try it and let me know if you have any problem.

Multiple models with ID in one view

Working on this project and I am stuck again. I have a view that I need to display a menu along the side. The menu is pulled from a table. Along the side of this, I have a question that is pulled from another table. Inside of this, there will be suggestions that are yet pulled from another table. With the question, I have a couple of inputs, radio buttons, and a text box for feedback which will end up in a different table. All of this has to take place with the ID from the main table so that when the information is saved in the results table it knows what the main record it belongs too. The page can be brought up with a /Audit/302 but when you change the submenu to the next question how do you get that question and maintain the ID. For Every question, there will be an entry for that ID. I have made relationships this is what it looks like.
August 02 2011
I have added a ViewModel that pulls a list of checkboxes from a table called Score (OK, Concern, N/A)
The page that i have is rendered with an ID it pulls a record from AuditSchedules and retrieves some info. In the Layout i also have a side menu (partial) that renders a list of actionlinks that will select different sections and a MainQuestion (partial). We work up to this point. Since i have added the viewModel to populate the checkboxes and save the text into a table with the ID of the AuditSchedule and MainQuestion. My issue is i am calling for id to select the ids from the table for the Scores and it is grabbing the id from the AuditSchedule. Giving me a no data found.
Here is my Controller:
//get
public ActionResult _Forms(int score)
{
AuditFormEdit viewModel = new AuditFormEdit();
viewModel.ScoreInstance = _db.Scores.Single(r => r.ScoreID == score);
viewModel.InitializeScoreCheckBoxHelperList(_db.Scores.ToList());
return View(viewModel);
}
//post
[HttpPost]
public ActionResult _Forms(int score, AuditFormEdit viewModel)
{
if (ModelState.IsValid)
{
viewModel.PopulateCheckBoxsToScores();
_db.Entry(viewModel.ScoreInstance).State = System.Data.EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("/");
}
else
{
return View(viewModel);
}
}
Here is my viewModel:
public class AuditFormEdit
{
public Models.Score ScoreInstance { get; set; }
public List<ScoreCardCheckBoxHelper> ScoreCardCheckBoxHelperList { get; set; }
public void InitializeScoreCheckBoxHelperList(List<Models.Score> ScoreList)
{
if (this.ScoreCardCheckBoxHelperList == null)
this.ScoreCardCheckBoxHelperList = new List<ScoreCardCheckBoxHelper>();
if (ScoreList != null
&& this.ScoreInstance != null)
{
this.ScoreCardCheckBoxHelperList.Clear();
ScoreCardCheckBoxHelper spacerProductCheckBoxHelper;
string spacerTypes =
string.IsNullOrEmpty(this.ScoreInstance.ScoreName) ?
string.Empty : this.ScoreInstance.ScoreName;
foreach (Models.Score scoreType in ScoreList)
{
spacerProductCheckBoxHelper = new ScoreCardCheckBoxHelper(scoreType);
if (spacerTypes.Contains(scoreType.ScoreName))
spacerProductCheckBoxHelper.Checked = true;
this.ScoreCardCheckBoxHelperList.Add(spacerProductCheckBoxHelper);
}
}
}
public void PopulateCheckBoxsToScores()
{
this.ScoreInstance.ScoreName = string.Empty;
var scoreType = this.ScoreCardCheckBoxHelperList.Where(x => x.Checked)
.Select<ScoreCardCheckBoxHelper, string>(x => x.ScoreName)
.AsEnumerable();
this.ScoreInstance.ScoreName = string.Join(", ", scoreType);
}
public class ScoreCardCheckBoxHelper : Models.Score
{
public bool Checked { get; set; }
public ScoreCardCheckBoxHelper() : base() { }
public ScoreCardCheckBoxHelper(Models.Score scoreCard)
{
this.ScoreID = scoreCard.ScoreID;
this.ScoreName = scoreCard.ScoreName;
}
}
}
Here is the link and controller that pulls the page up this is the Body of the layout:
public ActionResult Audit(int id)
{
var auditToDetail = _db.AuditSchedules.Single(r => r.AuditScheduleID == id);
return View(auditToDetail);
}
the link looks like this:
/AuditSchedule/Audit/257
Let me know if you need anything else.
I have used a code first approach and all tables have models with the relationships called out.
thank you
Your question is pretty general - but here are some things to think about.
First, in MVC3 you typically want to strongly type your views to your models. In your case you would want a single view for each model. You don't want "multiple multiple models in a view", but rather multiple views rendered together on a single page - all linked by some common data.
One way to accomplish this would be set write a "child actions" (use:[ChildActionOnly] attribute) in your controller for populating each of your individual models sending them to their respective indiviudal views. You can use the [Html.RenderAction][3] function within any view to render any other view. The easiest way to organize this is often with layouts 4 - You could render all your views using Html.RenderAction(), and then render your main form as the primary view (displayed in the layout with #RenderBody()).
To populate each of your models you will likely need to know some data (like an id), these can be stored in the ViewBag or ViewData, and passed in as objects in the Html.RenderAction function. (If you are using razor the call in your view might look something like:#{Html.RenderAction("actionName", new {object1 = "xyz", object2 ="abc"});} Just to make this clear, the logical flow will look like this
Populate the ViewBag with the data you will need to render your sub-views,
Populate your model for the main form and you call the main form's view (your primary view).
Your primary view defines a layout view, which in-turn calls Html.RenderAction, using the ViewBag data to set the appropriate objects.
The layout also renders the primary view as the "body" (#RenderBody()).
The end result of this is views that can be [strongly typed][7] to individual views, and individual controller actions for each model. This is a good thing, because it makes your views reusable anywhere, and it isolates the logic for populating each model (because each model has its own action in the controller). If you make subsequent changes to a model, it will be easy to know which Action/Model/View needs to be modified.
Below are some resources to get you started in understanding your options for rendering multiple models on a single page. I apologize for not lacing this post with nice links to helpful items, but as a new answerer, I was limited to two... Google will have to be your guide for the others.
Hope this helps - Best of Luck!
Resources:
Html.RenderAction and Html.Action - http://haacked.com blog
When to use Html.RenderPartial and Html.RenderAction in ASP.NET MVC Razor Views - http://www.arrangeactassert.com

Keeping selected item from dropdown box after page refresh

I have a dropdown box with a list of times for the user to choose from. My problem is that after the user picks their choice and then hits the submit button, the page is refreshed and then the dropdown box is set to default again - how can i have the users choice stay in the dropdown box even after a page reload? I am not sure what part of my code is needed best my Get and Post are long - but if there is a general example that would help.
CODE FROM CONTROLLER:
Here is one of my lists i load into the dropdown box:
IQueryable<User> users = _userRepository.FindAllForOffice(_currentUser.OfficeId);
userViewModel.Users = users.ToSelectList("UserId", "FullName",
userViewModel.UserId.ToString());
foreach (SelectListItem view in userViewModel.Users)
{
if (!viewData.ContainsKey(view.Text))
viewData.Add(view.Text, view.Value + "|user");
}
This is adding to the actual dropdown:
userViewModel.ViewData = viewData.ToSelectList("Value", "Key",
userViewModel.Value);
return View("UserSummary", userViewModel);
ON MY ASPX.CS page i have the following:
Page_Load
string viewType = null;
if(!String.IsNullOrEmpty(Request.QueryString["viewType"]))
{
viewType = Request.QueryString["viewType"];
}
if(!IsPostBack)
{ if (viewType == "user")
{
viewParams.Add("ViewName", "User Report");
var reportDataSource =
_userService.GetUsersReportData(beginDate, endDate, id);
reportViewer.Initialize("UserIndividual.rdlc",
new List<ReportDataSource> {reportDataSource}, viewParams);
}
I didn't add all the initialization for all the elements - didn't think it is really needed for this situation
Thanks
Check this odetocode.com article out.
To keep the selected value after a manual refresh, you could use a cookie, for example jquery.cookie. You would have to save the selected value on change and retrieve the value on page load.
I actually found a solution which was really simple and i guess i was overlooking it. I found that the same way i was passing in the values of the dates i could pass the value of the selected view type and it will remain in dropdown box until changed rather than changing after every page load.
I made the additions in my CONTROLLER file in my Get method after the button click.
this is my Post:
[HttpPost]
public ActionResult ResultSummary(ResultSummaryViewModel resultSummaryViewModel)
{
if (!ModelState.IsValid)
return View("ResultSummary", resultSummaryViewModel);
return RedirectToAction("ResultSummary",
new
{
beginDate = resultSummaryViewModel.BeginDate,
endDate = resultSummaryViewModel.EndDate,
value = resultSummaryViewModel.Value
});
}
And this is my Get:
[HttpGet]
public ActionResult ResultSummary(DateTime? beginDate = null, DateTime? endDate = null, string value="")
{
var resultSummaryViewModel = new ResultSummaryViewModel();
resultSummaryViewModel.BeginDate = beginDate;
resultSummaryViewModel.EndDate = endDate;
resultSummaryViewModel.Value = value;
.........
The code continues but this is the main part.

Categories