I am working with a link list. The list has items based on inserted values from textboxes (size, height, stock, price). . Through the button click the Add function takes values from texboxes and appends item but every time I add an item to the list instead of placing at the end of the list it always placed first. I am not sure why such behavior. How can I modify so it can append the item always to the end of the list? (I am displaying my test results on a fifth multiline textbox called results).
Code
public void Add()
{
textBoxResults.Clear();
int stock = Convert.ToInt32(Stock.Text);
string type = Type.Text;
double price = Convert.ToDouble(Price.Text);
int height = Convert.ToInt32(Height.Text);
Tree = new FruitTrees();
Tree.Stock = stock;
Tree.Type = type;
Tree.Price = price;
Tree.Height = height;
Total += Tree.Price * Tree.Stock;
Trees.AddLast(Tree);
}
Is this a school project? Just wondering why you aren't using System.Collections.Generic.LinkedList<T>.
LinkedList<FruitTrees> trees = new LinkedList<FruitTrees>();
It comes with its own AddLast method which does exactly what you want.
Also, I think your class name shouldn't be plural (FruitTree vs FruitTrees).
You could implement your own AddLast, something like this:
FruitTrees item = Trees.Retrieve(0);
while (item.Next != null)
{
item = item.Next;
}
item.Next = NewItem
Related
currently I have a combobox with three hard coded items.
Each item carries 2 values. I'm using a switch case statement to get the values for each item depending on which item is selected.
Switch(combobox.selectedindex)
{
case 0: // Item 1 in combobox
a = 100;
b = 0.1;
break;
case 1: // Item 2 in combobox
a = 300;
b = 0.5;
break;
//and so on....
}
I'm trying to add a feature to allow the user to add more items into the combobox with inputted a and b values. How would i be able to dynamically add case statements and define the values under each case condition? I've had a look at using a datatable instead but I don't know how to get multiple valuemembers out of the datatable when one item is selected.
Also, I would like to save the user added items and it's corresponding values to a .dat file. So when the program is re-opened it will be able to load the list of items added by the user from the file. I considered using streamwriter and readline for this but I'm unsure how it would be done.
You can use Binding on a combobox using the DataSource. The ComboBox can also be bound to other things than Primitive values (string/int/hardcoded values). So you could make a small class that represents the values you are setting in your switch statement, and then use the DisplayMember to say which property should be visible in the combobox.
An example of such a basic class could be
public class DataStructure
{
public double A { get; set; }
public int B { get; set; }
public string Title { get; set; }
}
Since you are talking about users adding values to the combobox dynamically, you could use a BindingList that contains the separate classes, this BindingList could be a protected field inside your class, to which you add the new DataStructure when the user adds one, and then automatically updates the combobox with the new value you added.
The setup of the ComboBox, can be done in either Form_Load, or in the Form Constructor (after the InitializeComponent() call), like such:
// your form
public partial class Form1 : Form
{
// the property contains all the items that will be shown in the combobox
protected IList<DataStructure> dataItems = new BindingList<DataStructure>();
// a way to keep the selected reference that you do not always have to ask the combobox, gets updated on selection changed events
protected DataStructure selectedDataStructure = null;
public Form1()
{
InitializeComponent();
// create your default values here
dataItems.Add(new DataStructure { A = 0.5, B = 100, Title = "Some value" });
dataItems.Add(new DataStructure { A = 0.75, B = 100, Title = "More value" });
dataItems.Add(new DataStructure { A = 0.95, B = 100, Title = "Even more value" });
// assign the dataitems to the combobox datasource
comboBox1.DataSource = dataItems;
// Say what the combobox should show in the dropdown
comboBox1.DisplayMember = "Title";
// set it to list only, no typing
comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
// register to the event that triggers each time the selection changes
comboBox1.SelectedIndexChanged += comboBox1_SelectedIndexChanged;
}
// a method to add items to the dataItems (and automatically to the ComboBox thanks to the BindingContext)
private void Add(double a, int b, string title)
{
dataItems.Add(new DataStructure { A = a, B = b, Title = title });
}
// when the value changes, update the selectedDataStructure field
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox combo = sender as ComboBox;
if (combo == null)
{
return;
}
selectedDataStructure = combo.SelectedItem as DataStructure;
if (selectedDataStructure == null)
{
MessageBox.Show("You didn't select anything at the moment");
}
else
{
MessageBox.Show(string.Format("You currently selected {0} with A = {1:n2}, B = {2}", selectedDataStructure.Title, selectedDataStructure.A, selectedDataStructure.B));
}
}
// to add items on button click
private void AddComboBoxItemButton_Click(object sender, EventArgs e)
{
string title = textBox1.Text;
if (string.IsNullOrWhiteSpace(title))
{
MessageBox.Show("A title is required!");
return;
}
Random random = new Random();
double a = random.NextDouble();
int b = random.Next();
Add(a, b, title);
textBox1.Text = string.Empty;
}
}
Like this, you have the selected item always at hand, you can request the values from the properties of the selected, and you don't have to worry about syncing the ComboBox with the items currently visible
From the documentation:
Although the ComboBox is typically used to display text items, you can add any object to the ComboBox. Typically, the representation of an object in the ComboBox is the string returned by that object's ToString method. If you want to have a member of the object displayed instead, choose the member that will be displayed by setting the DisplayMember property to the name of the appropriate member. You can also choose a member of the object that will represent the value returned by the object by setting the ValueMember property. For more information, see ListControl.
So you can just add objects that hold all the information, directly to the Items collection of the ComboBox. Later, retrieve the SelectedItem property and cast it back to the correct type.
I'm reading in a field from a database into a list, like so
PaceCalculator pace = new PaceCalculator();
List<PaceCalculator> Distancelist = new List<PaceCalculator>();
while (Reader.Read()) //Loops through the database and adds the values in EventDistance to the list
{
pace.Distance = (int)Reader["EventDistance"];
Distancelist.Add(pace);
}
I want to put the values into a listbox, but when I do it like this:
listBox1.DataSource = Distancelist;
It only shows the class name, which is PaceCalculator. It shows the right number of values, it just shows the class name instead. I want to see the integers in there.
You have two options,
Override ToString in your class to return the required string
or, if you only want to display Distance then specify that as DisplayMember
like:
listBox1.DisplayMember = "Distance";
listBox1.DataSource = Distancelist;
This will display you the Distance element from your list. Or you can override ToString in your class PaceCalculator like:
public override string ToString()
{
return string.Format("{0},{1},{2}", property1, property2, property3);
}
EDIT:
Based on your comment and looking at your code, You are doing one thing wrong.
this only displays the last value in the list, 46, 8 times
You are adding the same instance (pace) of your class in your list on each iteration. Thus it is holding the last value (46). You need to instantiate a new object in the iteration like:
while (Reader.Read())
{
PaceCalculator pace = new PaceCalculator();
pace.Distance = (int)Reader["EventDistance"];
Distancelist.Add(pace);
}
Specify the property of PaceCalculator to display.
listBox1.DataSource = Distancelist;
listBox1.DisplayMember = "Distance";
The ListBox control allows you to pick a property from the collection to display to the user.
There's also a ValueMember property that allows you to specify the value for each item in the ListBox. Assuming your data included an id called "SomeUniqueRecordId", for instance:
listBox1.ValueMember = "SomeUniqueRecordId";
I'm using the ObjectListViewand am trying to add images to my items. I got it to work by looping through all the items and then manually editing the image index per item. I would like to know if this is possible when adding the items. This is the code I have at the moment:
Adding the items
for (int i = 0; i < listName.Count; i++)
{
games newObject = new games(listName[i], "?");
lstvwGames.AddObject(newObject);
}
Adding the images
foreach (string icon in listIcon)
{
imglstGames.Images.Add(LoadImage(icon)); // Download, then convert to bitmap
}
for (int i = 0; i < lstvwGames.Items.Count; i++)
{
ListViewItem item = lstvwGames.Items[i];
item.ImageIndex = i;
}
It is not entirely clear to me what exactly you try to achieve, but there are several ways to "assign" an image to a row. Note that you probably have to set
myOlv.OwnerDraw = true;
which can also be set from the designer.
If you have a specific image for each of your model objects, its probably best to assign that image directly to your object and make it accessible through a property (myObject.Image for example). Then you can use the ImageAspectName property of any row to specify that property name and the OLV should fetch the image from there.
myColumn.ImageAspectName = "Image";
Another way to do it is using the ImageGetter of a row. This is more efficient if several of your objects use the same image, because you can fetch the image from anywhere you want or even use the assigned ImageList from the OLV by just returning an index.
indexColumn.ImageGetter += delegate(object rowObject) {
// this would essentially be the same as using the ImageAspectName
return ((Item)rowObject).Image;
};
As pointed out, the ImageGetter can also return an index with respect to the ObjectListView's assigned ImageList:
indexColumn.ImageGetter += delegate(object rowObject) {
int imageListIndex = 0;
// some logic here
// decide which image to use based on rowObject properties or any other criteria
return imageListIndex;
};
This would be the way to reuse images for multiple objects.
Both your approach and the one I show below will have problems if the list is ever sorted as sorting will change the order of the objects in the list. But really all you have to do is keep track of your object count in your foreach loop.
int Count = 0;
foreach (string icon in listIcon)
{
var LoadedImage = LoadImage(icon);
LoadedImage.ImageIndex = Count;
imglstGames.Images.Add(LoadedImage); // Download, then convert to bitmap
Count++;
}
I'm using a CheckedListBox (System.Windows.Forms.CheckListBox) and running through some code to populate items in the list using a DataSet. My problem is that I can't seem to figure out how to set the Selected Value property, or find the right property to set!
Here's my code that successfully adds in the items:
for (int i = 0; i < projectsDataSet.tblResources.Rows.Count; i++)
{
clbResources.Items.Add(projectsDataSet.tblResources.Rows[i]["Description"].ToString());
}
There are no useful overloads on the .Add method that takes a value parameter and I can't seem to get to a value property of an item.
I guess the bottom line of what I need is the items in the CheckedListBox to display items using one field from my DataSet (like a description) and use another to store that item's value (like a primary key), so would appreciate suggestions to achieve that, thanks!
First make a class for your list box items...
public class Thing
{
public string Key { get; set; }
public string Value { get; set; }
public override string ToString()
{
return Key + "--" + Value;
}
}
Then add items to your CheckListBox like so:
for (int i = 0; i < projectsDataSet.tblResources.Rows.Count; i++)
{
clbResources.Items.Add(new Thing()
{
Key = projectsDataSet.tblResources.Rows[i]["Key"].ToString(),
Value = projectsDataSet.tblResources.Rows[i]["Description"].ToString()
}, isChecked);
}
I had had the same issue. Luckily you there is workaround to this.
if the number of items and order of items in ListBox & DataTable is same then you can get the corresponding value as below
ListBox.SelectedIndexCollection items = checkedListBox1.SelectedIndices;
for(int i=0;i<items.Count;i++)
string selectedValue = projectsDataSet.tblResources.Rows[items[i]]["ValueColumn"].ToString();
I have quite a few radiobuttonLists in my ASP.net webform. I am dynamically binding them using the method shown below:
public static void PopulateRadioButtonList(DataTable currentDt, RadioButtonList currentRadioButtonList, string strTxtField, string txtValueField,
string txtDisplay)
{
currentRadioButtonList.Items.Clear();
ListItem item = new ListItem();
currentRadioButtonList.Items.Add(item);
if (currentDt.Rows.Count > 0)
{
currentRadioButtonList.DataSource = currentDt;
currentRadioButtonList.DataTextField = strTxtField;
currentRadioButtonList.DataValueField = txtValueField;
currentRadioButtonList.DataBind();
}
else
{
currentRadioButtonList.Items.Clear();
}
}
Now, I want to Display only the first Letter of the DataTextField for the RadioButton Item Text.
For example if the Value is Good I just want to Display G. If it Fair I want to display F.
How do I do this in C#
Thanks
You can't do what you want when you do the binding, so you have 2 options:
Modify the data you get from the table, before you do the binding.
After binding, go through each item and modify its Text field.
So, it you want to display "only the first Letter of the DataTextField for the RadioButton Item Text", you can do:
currentRadioButtonList.DataSource = currentDt;
currentRadioButtonList.DataTextField = strTxtField;
currentRadioButtonList.DataValueField = txtValueField;
currentRadioButtonList.DataBind();
foreach (ListItem item in currentRadioButtonList.Items)
item.Text = item.Text.Substring(0, 1);
If I misunderstood you and you want to display the first letter of the Value field, you can replace the last two lines with:
foreach (ListItem item in currentRadioButtonList.Items)
item.Text = item.Value.Substring(0, 1);
You could add a property to the type that is being bound (the one that contains Good, Fair, etc.) and bind to this property. If you will always be using the first letter, you could make it like so (adding in null checks, of course):
public string MyVar { get; set; }
public string MyVarFirstChar
{
get { return MyVar.Substring(0, 2); }
}