Pagination with a for loop getting startpage issue - asp.net-mvc-3

i have an extension method that does the pagination. There are 23 entries in the directory so 3 pages,
my controller in short:
public ActionResult Index(int? page)
{
List<ScormModuleInfo> modules = new List<ScormModuleInfo>();
string[] dirs = Directory.GetDirectories(scormRootDir);
int totalResults = dirs.Count();
int pageSize = PageSizeSettings.ScormPackages;
int totalPages = Math.Max(Convert.ToInt32(Math.Ceiling((double)totalResults / pageSize)), 1);
if (page >= 1)
{
int startresult = ((Math.Max(1, **page**) - 1) * pageSize) + 1;
int endresult = Math.Min(startresult + (pageSize - 1), totalResults);
for (int i = startresult; i <= endresult; i++)
{
//more code
}
}
in the view:
<div class="actions-left">
<%= Html.GlobalisedPageLinks(Amico.Web.Mvc.Extensions.Enums.PageLinksFormat.Empty, Model.CurrentPage, Model.PageSize, Model.Total, x => Url.Action("Index", "Scorm", new { area = "Admin", page = x }))%>
</div>
the extension method:
public static string GlobalisedPageLinks(this HtmlHelper html, Amico.Web.Mvc.Extensions.Enums.PageLinksFormat format, int currentPage, int pageSize, int totalResults, Func<int, string> pageUrl)
{
int totalPages = Math.Max(Convert.ToInt32(Math.Ceiling((double)totalResults / pageSize)), 1);
int startresult = ((Math.Max(1, currentPage) - 1) * pageSize) + 1;
int endresult = Math.Min(startresult + (pageSize - 1), totalResults);
string pagesText = html.Resource(Resources.Global.PageLinks.PageLinksFormatPages, currentPage, totalPages);
string resultsText = html.Resource(Resources.Global.PageLinks.PageLinksFormatResults, startresult, endresult, totalResults);
string firstText = html.Resource(Resources.Global.PageLinks.First);
string previousText = html.Resource(Resources.Global.PageLinks.Previous);
string nextText = html.Resource(Resources.Global.PageLinks.Next);
string lastText = html.Resource(Resources.Global.PageLinks.Last);
return "<span class='page-links'>" + html.PageLinks(format, currentPage, pageSize, totalResults, pageUrl,
pagesText, resultsText, firstText, previousText, nextText, lastText) + "</span>";
}
I get a red line on Math.Max(1, page) for startresult stating: best overload method is (decimal,decimal) i have some invalid arguments?

Try like this:
Math.Max(1, page ?? 1)
The reason for this is because the Max method expects an integer as second argument but you are passing it a nullable integer (your page parameter is declared as int? page). By using the null coalescing operator (??) you are indicating a default value if this parameter is null.

Related

Different PageSize for each page in itext 7

I need the page size to change to a certain page.
For example if page 3 i set pageSize A4.
If page 2 i set pageSize new Rectangle(155,155)
String line = "Hello! Welcome to iTextPdf";
Div div = new Div();
for (int i = 0; i < 30; i++) {
Paragraph element = new Paragraph();
element.add(line + " " + i);
paragraphs.add(element);
}
--------------
if(page==1) // This is just for an example. How I want it to be
pdf.setDefaultPageSize(PageSize.A5);
else if(page==3)
element.setDefaultPageSize(PageSize.A4);
You can override the DocumentRenderer class and customize #addNewPage:
private static class CustomDocumentRenderer extends DocumentRenderer {
public CustomDocumentRenderer(Document document) {
super(document);
}
#Override
protected PageSize addNewPage(PageSize customPageSize) {
if (customPageSize != null) {
document.getPdfDocument().addNewPage(customPageSize);
return customPageSize;
} else {
PageSize pageSize = definePageSizeBasedOnPageNumber(document.getPdfDocument().getNumberOfPages() + 1);
document.getPdfDocument().addNewPage(pageSize);
return pageSize;
}
}
private PageSize definePageSizeBasedOnPageNumber(int curPageNumber) {
if (curPageNumber % 2 == 1) {
return PageSize.A4;
} else {
return PageSize.A4.rotate();
}
}
}
Here we have a helper private method definePageSizeBasedOnPageNumber to define the page size based on the page number.
Using this customized renderer is very simple now: document.setRenderer(new CustomDocumentRenderer(document));
Full snippet of code at the highest execution level:
Document document = new Document(pdfDocument);
document.setRenderer(new CustomDocumentRenderer(document));
String line = "Hello! Welcome to iTextPdf";
for (int i = 0; i < 30; i++) {
Paragraph element = new Paragraph();
element.add(line + " " + i);
document.add(element);
}
document.close();

replacing a submitlink with indicatingAjaxButton

I have a form with a submitbutton which will get results from a database and updates a listview based on these results. If there is no result, a feedback message is shown. This all works fine.
Now I want to replace the submitlink with an IndicatingAjaxButton, so the user can see something happening when getting the result takes a long time.
The basic idea is this:
IndicatingAjaxButton submitLink = new IndicatingAjaxButton("submit", form) {
private static final long serialVersionUID = -4306011625084297054L;
#Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
Integer hourFrom = 0;
Integer hourTo = 0;
Integer minuteFrom = 0;
Integer minuteTo = 0;
hourFrom = Integer.parseInt(hour_from.getModelObject());
hourTo = Integer.parseInt(hour_to.getModelObject());
minuteFrom = Integer.parseInt(minute_from.getModelObject());
minuteTo = Integer.parseInt(minute_to.getModelObject());
Calendar from = Calendar.getInstance();
Calendar to = Calendar.getInstance();
Date dateFrom = date_from.getModelObject();
Date dateTo = date_to.getModelObject();
from.setTime(dateFrom);
to.setTime(dateTo);
from.set(Calendar.HOUR, hourFrom);
from.set(Calendar.MINUTE, minuteFrom);
to.set(Calendar.HOUR, hourTo);
to.set(Calendar.MINUTE, minuteTo);
if (topicQueueSelect.getModelObject() == null) {
error("Please select a message name.");
getSession().setAttribute("error", "");
}
if (to.before(from)) {
error("Date to must be after date from.");
getSession().setAttribute("error", "");
}
cal.setTimeInMillis(System.currentTimeMillis());
if (from.after(cal)) {
error("Date from must be in the past.");
getSession().setAttribute("error", "");
}
if (getSession().getAttribute("error") != null) {
getSession().removeAttribute("error");
return;
}
page.setModelObject(1);
List<Search> searchFields = (List<Search>) searchFieldsField
.getModelObject();
messageKeyDataList = messageController.search(
topicQueueSelect.getModelObject(), searchFields,
from.getTime(), to.getTime(),
maxResults.getModelObject(), page.getModelObject(),
sortorder);
if (messageKeyDataList.size() == 0) {
info("Search criteria didn't produce any results.");
result.setList(messageKeyDataList);
resultContainer.setVisible(false);
return;
}
resultContainer.setVisible(true);
resultSize = messageController.getResultSize();
int pages = (int) Math.ceil((float) resultSize
/ maxResults.getModelObject());
ArrayList<Integer> pageNumbers = new ArrayList<Integer>();
for (int n = 1; n <= pages; n++) {
pageNumbers.add(n);
}
page.setChoices(pageNumbers);
pageunder.setChoices(pageNumbers);
showing.setDefaultModelObject("Showing 1 to "
+ messageKeyDataList.size() + " out of " + resultSize
+ " messages");
lastSearch.put("topicQueue", topicQueueSelect.getModelObject());
lastSearch.put("searchFields", searchFields);
lastSearch.put("from", from.getTime());
lastSearch.put("to", to.getTime());
lastSearch.put("maxResults", maxResults.getModelObject());
result.setList(messageKeyDataList);
target.add(feedback);
}
};
The SubmitLink does show me either the ResultView with the new list, or the info message, the IndicatingAjaxButton doesn't. I know the form submit is called, because the system.out is being printed.
Any suggestions on this?
SubmitLink is non-Ajax component. Using it will repaint the whole page!
IndicatingAjaxButton is an Ajax component. You need to use the passed AjaxRequestTarget to add components which should be repainted with the Ajax response. For example the FeedbackPanel should be added to the AjaxRequestTarget.
I found that I had to do setOutputMarkupPlaceholderTag(true) on both the resultContainer and the feedback. After that adding them to the requesttarget works as expected.

Generic Orderby LINQ

I have a generic repository method to enable server side paging:
public virtual IEnumerable<T> GetList(out int totalPages, Expression<Func<T, bool>> filter = null,
Expression<Func<T, object>> orderby = null,
bool ascending = true,
string includeProperties = "",
int pageSize = 10, int pageNumber = 1)
{
IQueryable<T> query = c.Set<T>();
if (filter != null)
{
query = query.Where(filter);
}
query = includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Aggregate(query, (current, includeProp) => current.Include(includeProp));
if (orderby != null)
{
query = #ascending ? query.OrderBy(#orderby) : query.OrderByDescending(#orderby);
}
else
{
query = #ascending ? query.OrderBy(o => o.Id) : query.OrderByDescending(o => o.Id);
}
//totalPages = (int) Math.Ceiling((double)(Queryable.Count(query) / pageSize));
totalPages = 1;
if (pageSize > 0)
{
var skip = 0;
var take = pageSize;
if (pageNumber > 1)
{
skip = (pageNumber - 1) * pageSize;
take = pageSize + skip;
}
query = query.Take(take);
query = query.Skip(skip);
}
return query.ToList();
}
T is a base class inherited by my entities
I call this repository method from my service. and i call my service from my controller.
Now from my controller how do i create my orderby expression so that i can pass any column name?
What i've tried so far (found on stackoverflow):
var _OrderByProperty = typeof(Year).GetProperty("Id");
var _OrderByParameter = Expression.Parameter(typeof(Year), "x");
var _OrderByBody = Expression.Property(_OrderByParameter, _OrderByProperty.Name);
var _OrderByConverted = Expression.Convert(_OrderByBody, typeof(Object));
var _OrderByLambda = Expression.Lambda<Func<Year, object>>
(_OrderByConverted, _OrderByParameter);
var list = s.GetList(orderby: _OrderByLambda, totalPages: out totalPages, pageNumber: pageNumber, pageSize: pageSize, ascending: isAsc);
i'm getting the error
Unable to cast the type 'System.Int32' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types.

C#. Search array of strings for longest element

I want to know how I can get out everyone of the the longest persons if there are several with the same length?
If only one person is the longest, then it works fine and the longest person with it´s name will show in MessageBox. But if there are more than one who are the longest, this code will not work...
public partial class Form1 : Form
{
int[] längdArray = new int[5];
string[] namnArray = new string[5];
int namn = 0;
int längd = 0;
public Form1()
{
InitializeComponent();
}
private void btnVisa_Click(object sender, EventArgs e)
{
int längst = 0;
int längdvärdet = 0;
int längdindex = 0;
string name = textBox1.Text;
namnArray[namn] = name;
namn = namn + 1;
textBox1.Clear();
int centimeter = int.Parse(textBox2.Text);
längdArray[längd] = centimeter;
längd++;
textBox2.Clear();
listBox1.Items.Add(name + " " + centimeter + " centimeter ");
if (längd == 5)
{
btnVisa.Enabled = false;
foreach (int antalLängder in längdArray)
{
if (antalLängder > längst)
{
längst = antalLängder;
längdvärdet = längdindex;
}
längdindex++;
}
string test = namnArray[längdvärdet]
MessageBox.Show(" Längsta person är " + test + " som är " + längst + " centimeter lång ");
}
Define behavior you want your app to present when there is more than one person. Should all display, or any one, or other? Try to use object constructions, it's easier to operate on them. C# is an object-oriented language. Put name and length in one structure then use LINQ.

syntax to return a number of results per page

I have this linq statement that returns result and i wanted to add the specifications of how many items are displayed per page. I know the default is 10 per page how can i change it to 40?
var _roster = DataCBase.StoredProcedures.GetUser<Users>(userID, r => new Users
{
Name = RosterColumnMap.Name(r),
Email = RosterColumnMap.Email(r)
});
Get User
public virtual IEnumerable<T> GetUser<T>(int userId, Func<IDataRecord, T> modelBinder, int resultsPerPage = 10, int pageNumber = 1)
{
if (userId < 1)
throw new NullReferenceException("The sectionId cannot be null, when retreiving an element");
if (resultsPerPage < 1)
resultsPerPage = 1; // enforce bare minimum result set
if (pageNumber < 1)
pageNumber = 1; // enforce one-based page numbering
SqlCommand _command = new SqlCommand("dbo.GetUser");
_command.CommandType = CommandType.StoredProcedure;
_command.Parameters.Add(new SqlParameter { ParameterName = "userId", SqlDbType = SqlDbType.Int, Value = userId });
_command.Parameters.Add(new SqlParameter { ParameterName = "resultsPerPage", SqlDbType = SqlDbType.Int, Value = resultsPerPage });
_command.Parameters.Add(new SqlParameter { ParameterName = "pageNumber", SqlDbType = SqlDbType.Int, Value = pageNumber });
return DbInstance.ExecuteAs<T>(_command, modelBinder);
}
Neither Linq nor entity framework have any default number of records 'per page'. But since your GetUser function includes a resultsPerPage parameter, you can just do this:
var _roster = DataCBase.StoredProcedures.GetUser<Users>(userID, r => new Users
{
Name = RosterColumnMap.Name(r),
Email = RosterColumnMap.Email(r)
}, 40);
To limit the number of results in Linq use the the Enumerable.Take method:
var _roster = DataCBase.StoredProcedures.GetUser<Users>(userID, r => new Users
{
Name = RosterColumnMap.Name(r),
Email = RosterColumnMap.Email(r)
}).Take(40);

Resources