I've to show user details in DataGridView with pagination and almost done working with it. The problem is when I use skip and Take in LINQ, it doesn't show any data but without it works as follows:
grdUserDetails.DataSource = aUserDetail; //shows list of user details
grdUserDetails.DataSource = aUserDetail.Skip(startRow).Take(pageSize); //Doesn't show anything
This is the code that I've tried so far:
public int pageSize = 1;
public Users()
{
InitializeComponent();
BindDataGridView(1);
}
private void BindDataGridView(int pageIndex)
{
List<UserDetails> aUserDetail = null;
aUserDetail = GetUserDetails();
totalRecordCount = aUserDetail.Count;
int startRow = pageIndex * pageSize;
grdUserDetails.DataSource = aUserDetail.Skip(startRow).Take(pageSize); //Here is the main issue that I am stuck with
BindPager(totalRecordCount, pageIndex);
}
private void BindPager(int recordCount, int currentPage)
{
double getPageCount = (double)((decimal)totalRecordCount / (decimal)pageSize);
int pageCount = (int)Math.Ceiling(getPageCount);
List<ListItem> lstItem = new List<ListItem>();
if (currentPage > 1)
{
lstItem.Add(new ListItem { Text = "First", Value = "1" });
}
if (currentPage > 1)
{
lstItem.Add(new ListItem { Text = "<<", Value = (currentPage - 1).ToString() });
}
for (int i = 1; i <= recordCount; i++)
{
lstItem.Add(new ListItem { Text = i.ToString(), Value = i.ToString(), Selected = i == currentPage });
}
if (currentPage < pageCount)
{
lstItem.Add(new ListItem { Text = ">>", Value = (currentPage + 1).ToString() });
}
if (currentPage != pageCount)
{
lstItem.Add(new ListItem { Text = "Last", Value = pageCount.ToString() });
}
plPager.Controls.Clear();
int count = 0;
foreach (ListItem lst in lstItem)
{
Button btnPage = new Button();
btnPage.Location = new System.Drawing.Point(38 * count, 6);
btnPage.Size = new System.Drawing.Size(36, 20);
btnPage.Name = lst.Value;
btnPage.Text = lst.Text;
btnPage.Enabled = !lst.Selected;
btnPage.Click += new System.EventHandler(this.ListItem_Click);
plPager.Controls.Add(btnPage);
count++;
}
}
private void ListItem_Click(object sender, EventArgs e)
{
Button btnPager = (sender as Button);
this.BindDataGridView(int.Parse(btnPager.Name));
}
I've used two classes for the WinForm project. One is the UserDetails and another is Page to bind controls dynamically with a Panel:
public class ListItem
{
public string Text { get; set; }
public string Value { get; set; }
public bool Selected { get; set; }
}
public class UserDetails
{
public int Id { get; set; }
public string Name { get; set; }
}
public List<UserDetails> GetUserDetails()
{
List<UserDetails> lst = new List<UserDetails>
{
new UserDetails { Id = 1001, Name = "John" },
new UserDetails { Id = 1001, Name = "Jack" }
};
return lst;
}
Finally in the form, I've DataGridView named grdUserDetails and a panel plPager to show user details and the pagination. I am hoping, it would be a silly mistake and missed something doing so.
Two things.
1) startRow needs to be less by one because of zero-based indexing.
2) Your LINQ needs to be converted to a List<>.
So, try it this way:
grdUserDetails.DataSource = aUserDetail.Skip(startRow - 1).Take(pageSize).ToList();
Related
I currently have this loop:
if (lists.Date.Count() == 0)
{
message = "There Have Been No Merged Pull Requests In This Repository";
}
else
{
for (int i = 0; i < lists.Date.Count(); i++)
PullRequests = new List<PullRequestDetails>
{
new PullRequestDetails()
{
Title = lists.ShortRequestTitle[i],
Name = lists.Name[i],
Date = lists.Date[i],
CommitLink = lists.ShortCommitList[i],
},
};
}
which takes strings from lists and sets them in this model:
public class PullRequestDetails
{
public string? Title { get; set; }
public string? Name { get; set; }
public string? Date { get; set; }
public string? CommitLink { get; set; }
}
I want my HTML to display every item from the list when the button is clicked, but currently it is only displaying the last item from the list:
#if (Model.PullRequests != null)
{
#foreach (var requests in Model.PullRequests)
{
<tbody>
<tr>
<td>#requests.Title</td>
<td>#requests.Name</td>
<td>#requests.Date</td>
<td> Link </td>
</tr>
</tbody>
}
}
This works when I manually add each value of the list, but his gives an out of range exception when there are less or more than 4 values in each list (which there are in most cases):
if (lists.Date.Count() == 0)
{
html = "There Have Been No Merged Pull Requests In This Repository";
}
else
{
for (int i = 0; i < lists.Date.Count(); i++)
PullRequests = new List<PullRequestDetails>
{
new PullRequestDetails()
{
Title = lists.ShortRequestTitle[0],
Name = lists.Name[0],
Date = lists.Date[0],
CommitLink = lists.ShortCommitList[0]
},
new PullRequestDetails()
{
Title = lists.ShortRequestTitle[1],
Name = lists.Name[1],
Date = lists.Date[1],
CommitLink = lists.ShortCommitList[1]
},
new PullRequestDetails()
{
Title = lists.ShortRequestTitle[2],
Name = lists.Name[2],
Date = lists.Date[2],
CommitLink = lists.ShortCommitList[2]
},
new PullRequestDetails()
{
Title = lists.ShortRequestTitle[3],
Name = lists.Name[3],
Date = lists.Date[3],
CommitLink = lists.ShortCommitList[3]
},
};
}
So how can I fix this with a loop?
Just as #Camilo Terevinto said you need too take the List instantiation out of the loop
if (lists.Date.Count() == 0)
{
message = "There Have Been No Merged Pull Requests In This Repository";
}
else
{
PullRequests = new List<PullRequestDetails>();
for (int i = 0; i < lists.Date.Count(); i++)
{
PullRequests.Add(new PullRequestDetails()
{
Title = lists.ShortRequestTitle[i],
Name = lists.Name[i],
Date = lists.Date[i],
CommitLink = lists.ShortCommitList[i]
});
};
}
The button 1-10 are the items;
the pos screenshot
codes i used but doesn't work maybe it's wrong but i can't find answers on the internet
private void enterPayment_Click(object sender, EventArgs e)
{
label1.Text = "Payment";
//price.ReadOnly = false;
//price.Text = "0.00";
//price.Focus();
//Kukunin ko yung total ng List Items
double total = 0;
int ilan = orders.Items.Count;
for (int i = 0; i >= ilan; i++)
{
string item = orders.Items[i].ToString();
int Index = item.IndexOf("#");
int Length = item.Length;
string presyoString = item.Substring(Index + 1, Length - Index - 1);
double presyoDouble = double.Parse(presyoString);
total += presyoDouble;
//price.Text = (total + ".00");
}
price.Text = (total + ".00");
}
I strongly recommend that you use the listbox as a view only, not to be use to perform the mathematical operation. The data can be use in collection such as List so that you can perform better operation.
For example, at program load, I will add product information on List<T> and on form, I place a tag in the button consider it as product Id. So, when I click on the button, it will pass the tag property and from there, I will search the product information on list regarding my Id and add into another final List<T> and get the sum of it.
public partial class Form1 : Form
{
private List<ProductDisplay> listProductDisplay = new List<ProductDisplay>();
private List<ProductInformation> listProductInfo = new List<ProductInformation>();
public Form1()
{
InitializeComponent();
LoadProduct();
}
private void LoadProduct()
{
listProductDisplay = new List<ProductDisplay>()
{
new ProductDisplay{ProdID = 1,ProdName = "Chargrilled Burger",ProdPrice = 330.00m},
new ProductDisplay{ProdID = 2,ProdName = "Mushroom N' Swish",ProdPrice = 330.00m},
new ProductDisplay{ProdID = 3,ProdName = "Chicken Burger",ProdPrice = 250.00m},
new ProductDisplay{ProdID = 4,ProdName = "Steak Loader",ProdPrice = 220.00m},
new ProductDisplay{ProdID = 5,ProdName = "Cookie Sandwich",ProdPrice = 125.00m},
new ProductDisplay{ProdID = 6,ProdName = "Cookie Sundae",ProdPrice = 175.00m},
new ProductDisplay{ProdID = 7,ProdName = "Chicken Nuggets",ProdPrice = 145.00m},
new ProductDisplay{ProdID = 8,ProdName = "Curly Fries",ProdPrice = 75.00m},
new ProductDisplay{ProdID = 9,ProdName = "Sprite",ProdPrice = 50.00m},
new ProductDisplay{ProdID = 10,ProdName = "Coke",ProdPrice = 50.00m}
};
}
private void InsertOrder_ButtonClick(object sender, EventArgs e)
{
try
{
Button btn = (Button)sender;
int number = Convert.ToInt32(btn.Tag);
var itemProduct = listProductDisplay.First(x => x.ProdID == number);
ProductInformation prod = new ProductInformation
{
ProdID = itemProduct.ProdID,
ProdName = itemProduct.ProdName,
ProdPrice = itemProduct.ProdPrice,
ProdQty = 1
};
prod.ProdDisplayName = $"{prod.ProdQty}x {prod.ProdName} #{prod.ProdPrice.ToString("F")} = {(prod.ProdPrice * prod.ProdQty).ToString("F")}";
listProductInfo.Add(prod);
listBoxItem.DataSource = null;
listBoxItem.DataSource = listProductInfo;
listBoxItem.DisplayMember = "ProdDisplayName";
listBoxItem.ValueMember = "ProdID";
var price = listProductInfo.Sum(t => (t.ProdPrice * t.ProdQty));
txtPayment.Text = price.ToString("F");
}
catch (Exception ex)
{
MessageBox.Show("Failed to insert order");
throw;
}
}
}
public class ProductDisplay
{
public int ProdID { get; set; }
public string ProdName { get; set; }
public decimal ProdPrice { get; set; }
}
public class ProductInformation
{
public int ProdID { get; set; }
public string ProdName { get; set; }
public string ProdDisplayName { get; set; }
public decimal ProdPrice { get; set; }
public int ProdQty { get; set; }
}
Parsing and extracting values from a string like that is very error prone and brittle. What happens if the order of fields in your line changes? Or if you add currency symbols?
#Luiey's solution is the smartest way to go ahead. But if for some reason you cannot make so many changes to your code, the bare minimum you want to do is store the items in a list as a custom object with statically typed fields for price, quantity and total. The ListBox class invokes a ToString() at the time of rendering items. So you can easily override this method to prepare the output string according to your needs.
private class LineItem
{
public LineItem()
{
Quantity = 0;
Description = string.Empty;
Price = 0;
}
public int Quantity
{
get;
set;
}
public string Description
{
get;
set;
}
public int Price
{
get;
set;
}
public int Total
{
get
{
return Quantity * Price;
}
}
public override string ToString()
{
return $"{Quantity} × {Description} # {Price} = {Total}";
}
}
Then you add an item to your ListBox like this.
var item = new LineItem()
{
Quantity = 1,
Description = "Foo bar",
Price = 10
};
listBox1.Items.Add(item);
And add them up like this.
var items = listBox1.Items.Cast<LineItem>().ToArray();
var accumulator = 0;
accumulator = items.Aggregate(accumulator, (a, i) => a + (i.Quantity * i.Price), (a) => a);
I'm developing a web browser in C# using Visual Studio 2017. I am trying to save the user's search history in a database and display it in a listbox. However, the database and listbox are empty. I have no idea why it's not working.
I have a bookmark button that works in the same way. It functions fine. The bookmarks show up in the listbox.
Any thoughts as to why the history listbox is always empty?
public class HistoryItem
{
public string URL { get; set; }
public string Title { get; set; }
public DateTime Date { get; set; }
public int Id { get; set; }
}
public static void AddItem(HistoryItem item)
{
var adapter = new HistoryTableAdapter();
adapter.Insert(item.URL, item.Title, item.Date.ToShortDateString());
}
public static List<HistoryItem> GetItems()
{
var adapter = new HistoryTableAdapter();
var results = new List<HistoryItem>();
var rows = adapter.GetData();
foreach (var row in rows)
{
var item = new HistoryItem();
item.URL = row.URL;
item.Title = row.Title;
item.Date = DateTime.Parse(row.Date);
item.Id = row.Id;
results.Add(item);
}
return results;
}
private void DisplayLabel(object sender, WebBrowserDocumentCompletedEventArgs e)
{
toolStripStatusLabel1.Text = "Done";
toolStripProgressBar1.Value = 0;
var item = new HistoryItem();
item.URL = toolStripTextBox1.Text;
item.Title = webBrowser1.DocumentTitle;
item.Date = DateTime.Now;
HistoryManager.AddItem(item);
}
private void HistoryManager_Load(object sender, EventArts e)
{
var items = HistoryManager.GetItems();
foreach (var item in items)
{
HistoryListBox.Items.Add(string.Format("{0} ({1}) [{2}]", item.Title, item.URL, item.Date));
}
}
I have a ListView which gets data directly from the database. I want to use it to search for a record using any of the variables, i.e. name, number, or location. Currently I am able to search but using only one variable.
This is my code:
public void searchlist()
{
if (searchbox.Text != "")
{
for (int i = listView1.Items.Count - 1; i >= 0; i--)
{
var item = listView1.Items[i];
if (item.Text.Contains(searchbox.Text))
{
item.BackColor = SystemColors.Highlight;
item.ForeColor = SystemColors.HighlightText;
}
else
{
listView1.Items.Remove(item);
}
}
if (listView1.SelectedItems.Count == 1)
{
listView1.Focus();
}
}
else
{
loadthelist();
}
}
Looks like you need this:
private class TestClass
{
public int Id
{
get;
set;
}
public string Text
{
get;
set;
}
public string Detail
{
get;
set;
}
}
private void ListViewSearch_Load(object sender, EventArgs e)
{
List<TestClass> source = new List<TestClass>();
source.Add(new TestClass { Id = 1, Text = "one", Detail = "D1" });
source.Add(new TestClass { Id = 2, Text = "two", Detail = "D2" });
source.Add(new TestClass { Id = 3, Text = "three", Detail = "D1" });
source.Add(new TestClass { Id = 4, Text = "four", Detail = "D3" });
source.Add(new TestClass { Id = 5, Text = "five", Detail = "D6" });
source.Add(new TestClass { Id = 6, Text = "5", Detail = "D6" });
listView1.Columns.Add("Id");
listView1.Columns.Add("Text");
listView1.Columns.Add("Detail");
source.ForEach(x =>
{
ListViewItem item = new ListViewItem(x.Id.ToString());
item.UseItemStyleForSubItems = false;
item.SubItems.Add(x.Text);
item.SubItems.Add(x.Detail);
listView1.Items.Add(item);
});
listView1.View = View.Details;
listView1.GridLines = true;
comboBox1.DataSource = listView1.Columns;
comboBox1.DisplayMember = "Text";
comboBox1.ValueMember = "Text";
}
private void textBox1_Leave(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(textBox1.Text))
{
foreach (ListViewItem item in listView1.Items)
{
for (int subItemIndex = 0; subItemIndex < item.SubItems.Count; subItemIndex++)
{
if (subItemIndex == comboBox1.SelectedIndex && item.SubItems[subItemIndex].Text.Contains(textBox1.Text))
{
item.SubItems[subItemIndex].BackColor = SystemColors.Highlight;
item.SubItems[subItemIndex].ForeColor = SystemColors.HighlightText;
}
else
{
item.SubItems[subItemIndex].BackColor = Color.Transparent;
item.SubItems[subItemIndex].ForeColor = SystemColors.WindowText;
}
}
}
}
}
I want to populate my ListBox by a list of objects with properties , and I want to know how to define the listbox to display a certain property within this object which is some text,
and the other is the name of methods to be invoked while the listBox Items are clicked (SelectIndexChanged)
Hope this helps.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//Create a listbox, with given height/width and top/left
var lstBox = new ListBox
{
Width = 300,
Height = 300,
Top = 10,
Left = 10
};
//Add the listbox to your form
this.Controls.Add(lstBox);
//Create a list of your customclass
var listCustomClass = new List<CustomClass>();
//Populate the list with values
for (int i = 0; i < 50; i++)
{
//create an instanze of your customclass
var customClass = new CustomClass();
//set properties of your class
customClass.Name = "Name " + i;
customClass.Description = "Description " + i;
if (i % 2 == 0)
customClass.MethodName = "CallMeBaby";
else
customClass.MethodName = "CallMeBabyWithParameter";
customClass.RandomProperty1 = "RandomProperty1 " + i;
//add the newly created customclass into your list
listCustomClass.Add(customClass);
}
//set the listbox to display or value what you need
lstBox.DisplayMember = "Description"; //Name of a property inside the class CustomClass
lstBox.ValueMember = "Name"; //Name of a property inside the class CustomClass
//set the datasource
lstBox.DataSource = listCustomClass;
//register the selectedindexchanged event
lstBox.SelectedIndexChanged += lstBox_SelectedIndexChanged;
}
private void lstBox_SelectedIndexChanged(object sender, EventArgs e)
{
//get the listbox from the sender
var lstBox = (sender as ListBox);
if (lstBox != null)
{
//safe cast the selecteditem to your customclass to get full access to any public property with the class definition
var customClass = lstBox.SelectedItem as CustomClass;
if (customClass != null)
{
//do what ever you want with the object and its properties
var name = customClass.Name;
var desription = customClass.Description;
var methodName = customClass.MethodName;
var randomProperty1 = customClass.RandomProperty1;
//call a certain method based on a string within the object
if (methodName == "CallMeBaby")
CallMeBaby();
else if (methodName == "CallMeBabyWithParameter")
CallMeBaby(name);
}
}
}
//declare the methods that are being called
private void CallMeBaby(string value)
{
//Access the parameter and do something
if (value == "HelloWorld!")
{
//Do something...
}
}
//parameterless method to show the possibilities...
private void CallMeBaby()
{
//Do something...
}
//define a public class
public class CustomClass
{
//random properties, can be extended to have what ever your need
public string Name { get; set; }
public string Description { get; set; }
public string MethodName { get; set; }
public string RandomProperty1 { get; set; }
}
}