I have populated a listBox with items of type:
Tuple<List<Point>,List<int>>
Now when I run my application the listBox window display items like so:
(System.Collection.Generic.List'1[System.Drawing.Point].Systen,Collection...)
(System.Collection.Generic.List'1[System.Drawing.Point].Systen,Collection...)
(System.Collection.Generic.List'1[System.Drawing.Point].Systen,Collection...)
Instead I want listBox to display each item with string "Region" + item's index.
Like so:
Region0
Region1
Region2
...
To populate the listBox I use the following code:
listBoxPossibleCandidates.DataSource = possibleCandidates;
And possibleCandidates are populated like this with a loop:
possibleCandidates.Add(Tuple.Create(regionPoints, regionIntensities));
Okay, I found how to do this now.
It's done through ListControl.DisplayMember Property.
The reason it was displaying (System.Collection.Generic.List`1[System.Drawing.Point].Systen,Collection...) is because of this:
"If the specified property does not exist on the object or the value of DisplayMember is an empty string (""), the results of the object's ToString method are displayed instead."
Source: http://msdn.microsoft.com/en-us/library/system.windows.forms.listcontrol.displaymember(v=vs.110).aspx
Code I used:
class Region
{
private int myIndex;
private List<Point> regionCoordinates;
private List<int> regionIntensitiesDistinct;
public Region(List<Point> regionCoordinates, List<int> regionIntensities, int index)
{
this.regionCoordinates = regionCoordinates;
this.regionIntensitiesDistinct = regionIntensities.Distinct().ToList();
this.myIndex = index;
}
public string MyDescription
{
get
{
return "Region-" + myIndex;
}
}
public List<Point> getRegionCoordinates()
{
return regionCoordinates;
}
public List<int> getRegionIntensitiesDistinct()
{
return regionIntensitiesDistinct;
}
}
Now this is how I populate my listBox:
List<Region> possibleCandidates = new List<Region>();
//using loop I add all the regions:
possibleCandidates.Add(new Region(regionPoints, regionIntensities, possibleCandidates.Count));
//after possibleCandidates are populated I pass them to the listBox for display
listBoxPossibleCandidates.DataSource = possibleCandidates;
listBoxPossibleCandidates.DisplayMember = "MyDescription";
The listBox output is now:
* Region-0
* Region-1
* Region-2
* ...
Related
I'm using a ComboBox with items having text and value. Now, I want to simply make an item selected by comparing its value with the provided value. I'm iterating through the items and comparing as follow. Below code works fine, but is there a better or more simpler way to do this? I found a possible duplicate here but it works with the string value not integer.
foreach (ComboboxItem item in this.CampaignList.Items)
{
if (Convert.ToInt16(item.Value) == objAACampaign.CompanyId)
{
this.CampaignList.SelectedIndex = this.CampaignList.Items.IndexOf(item);
break;
}
}
Use display and value memeber
Create custom class like this:
class MyCustomClass
{
//important to have get set part
public _int { get; set; }
public _string { get; set; }
}
now load data you want to display inside List<MyCustomClass>() and then bind that list to combobox and set it's display and value member like this:
myComboBox.DisplayMember = "_string";
myComboBox.ValueMember = "_int";
myComboBox.DataSource = myList; //this is List<MyCustomClass>
Now simply use myComboBox.SelectedValue = valueYouWant
IMPORTANT!!!
Declare displayMember and valueMember before binding datasource to combobox because of perfomance. Search internet for more info.
Is it possible to sum up all of the item's price inside a ListBox? I have this ListBox that displays items from a DataGridView, and each of their prices are in priceTextBox Please refer from the picture below.
What I want to do is to display the sum of all the item's price and display it at the totalTextBox.
I have already done this code but I think this won't work.
private void menuListBox_SelectedValueChanged(object sender, EventArgs e)
{
int x = 0;
string Str;
foreach (DataGridViewRow row in menuDataGrid.Rows) //this part displays the price of each item to a textbox so this is good.
{
if (row.Cells[3].Value.ToString().Equals(menuListBox.SelectedItem.ToString()))
{
pricetxtbox.Text = row.Cells[5].Value.ToString();
break;
}
}
foreach (string Str in row.Cells[5].Value.ToString().Equals(menuListBox.SelectedItem.ToString())) //now this is the part where I want to happen the adding the prices of all items in the listbox. this also gives me an error at row saying it doesn't exist in the context
{
x = x + Convert.ToInt32(Str);
totaltxtbox.Text = x;
}
}
Will appreciate any help! Thanks!
Try this out...
Func<string, DataGridViewRow> getRow = (menuCode) =>
{
return menuDataGrid.Rows.Cast<DataGridViewRow>()
.First(r => ((string)r.Cells[3].Value).Equals(menuCode));
};
var selected = menuListBox.SelectedItem.ToString();
pricetxtbox.Text = getRow(selected).Cells[5].Value.ToString();
totaltxtbox.Text = menuListBox.Items.Cast<object>()
.Select(o => o.ToString())
.Select(i => (int)getRow(i).Cells[5].Value)
.Sum()
.ToString();
I think you should change your approach, by separating completely data and display.
To do that, you could create a class which will contain data for each row of your DataGrid :
public class MyItem
{
public string Caption { get; set; }
public int Price { get; set; }
}
And then in your codebehind, you store a list of these items :
private List<MyItem> AllItems = new List<MyItem>();
Finally, you set this collection as the source of your DataGrid :
menuDataGrid.DataSource = AllItems;
Then, all your data is stored in a collection you own, and to sum prices it's much simpler :
using System.Linq;
private int ComputeSum()
{
return (AllItems.Sum(item => item.Price));
}
The next step is to use Binding and a BindingList, wich allows the DataGrid to refresh automatically when new items are added in "AllItems": see this well explained post.
I found one similar question in StackOverflow, but it has no answers. I'm trying to bind a IList<string> to a DataGridView as its DataSource, but instead of it output the list of strings, like in a ListView, it outputs me the properties of the elements in the list, in this case, Length.
My code:
public void FindMatches()
{
const string regex = #"\{([a-zA-Z_][a-zA-Z0-9_]*)\}";
IList<string> names = (from Match match in Regex.Matches(ObterConteudoArquivo(), regex) select match.Value).ToList();
_view.Lista = names;
}
Now that I have a list stored in List that contains all my matches, example given { "{CP}", "{DP}", "{EP"} }, I want to bind them to my DataGridView:
public IList<string> Lista
{
set
{
ltvCampos.DataSource = value;
}
}
This binds only the Length of each string.
I also did:
public IList<string> Lista
{
set
{
foreach (string name in value)
{
DataGridTextBox row = new DataGridTextBox();
row.Text = name;
ltvCampos.Rows.Add(row);
}
}
}
The lexer says:
Method with 'params' is invoked. Have you intended to call more specific method 'int Add(object)'?
You need to wrap your strings in a class, which exposes them as public properties with both a setter and a getter:
class aString { public string theString { get; set; }
public aString(string s) { theString = s; } }
Now create a list of strings..
List<aString> theStrings = new List<aString>();
..and fill it with your Matches:
theStrings = (from Match match in Regex.Matches(text, regex)
select new aString(match.Value)).ToList();
Now you can bind your list to the DGV:
ltvCampos.DataSource = theStrings;
For added functionality you may want to insert one or two more layers of binding by using a BindingList (which among others will raise change events):
var blist = new BindingList<aString>(theStrings);
ltvCampos.DataSource = theStrings;
or both a BindingList and a BindingSource, which will present you with a wider range of options and methods:
var blist = new BindingList<aString>(theStrings);
var source = new BindingSource(blist, null);
ltvCampos.DataSource = source ;
Take a look at the answer on this link. I think it is going to help you. They are using a BindingList<> instead of an IList<>
I have a ListBox (sortedListBox) which I have populated like this by the items in a Combobox (allItemsComboBox):
int index = sortedListBox.FindString(allItemsComboBox.Text, -1);
if (index == -1)
{
var item=new { Text = allItemsComboBox.Text , Value = allItemsComboBox.Value};
sortedListBox.Items.Add(item);
}
The DisplayedMember of sortedListBox is "Text" and ValueMember of it is "Value".
Now I want to iterate through all items in the ListBox and get its values:
public static string ListBoxToString(ListBox lb)
{
List<string> values = new List<string>();
for (int i = 0; i < lb.Items.Count; i++)
{
values.Add(lb.Items[i].ToString());
}
string result = String.Join(",", values);
return result;
}
In this line: values.Add(lb.Items[i].ToString()); I get:
{ Text = "Size" , Value = "cte1.Size"}
I just want to have the value , which is "cte1.Size"
How can I iterate through the items in the ListBox and get the ValueMember of these?
I don't know that there's any way to ask the ListBox to evaluate the ValueMember for you in that way... and because you're using an anonymous type, it becomes harder to get the value.
Options:
Use a named type instead, and cast each item to that
Use dynamic typing
For example:
public static string ListBoxToString(ListBox lb)
{
var values = lb.Items
.Cast<dynamic>()
.Select(x => x.Value.ToString());
return string.Join(",", values);
}
Dynamic typing provides the most immediate fix, but I'd strongly encourage you to consider using a custom type. (It needn't take more than a few lines to write.)
There are two problems with your approach:
1.) The ListBox stores items as a collection of objects which means accessing them with listBox.Items[idx] will only give you back an object and not the actual type. You could get around that with casting it to the appropriate type but it won't work in your case because of the next point.
2.) You create your items as anonymous objects with var item = new { ... }. You can't cast to this kind of type. You could use the dynamic keyword to get around that but I wouldn't do that as you lose type safety.
What you could do is create a simple class for the date you want to store and use that instead of an anonymous type:
class MyData
{
public string Text { get; set; }
public string Value { get; set; }
}
Creating an item(Under the key) is easy,but how to add subitems(Value)?
listView1.Columns.Add("Key");
listView1.Columns.Add("Value");
listView1.Items.Add("sdasdasdasd");
//How to add "asdasdasd" under value?
You whack the subitems into an array and add the array as a list item.
The order in which you add values to the array dictates the column they appear under so think of your sub item headings as [0],[1],[2] etc.
Here's a code sample:
//In this example an array of three items is added to a three column listview
string[] saLvwItem = new string[3];
foreach (string wholeitem in listofitems)
{
saLvwItem[0] = "Status Message";
saLvwItem[1] = wholeitem;
saLvwItem[2] = DateTime.Now.ToString("dddd dd/MM/yyyy - HH:mm:ss");
ListViewItem lvi = new ListViewItem(saLvwItem);
lvwMyListView.Items.Add(lvi);
}
Like this:
ListViewItem lvi = new ListViewItem();
lvi.SubItems.Add("SubItem");
listView1.Items.Add(lvi);
Suppose you have a List Collection containing many items to show in a ListView, take the following example that iterates through the List Collection:
foreach (Inspection inspection in anInspector.getInspections())
{
ListViewItem item = new ListViewItem();
item.Text=anInspector.getInspectorName().ToString();
item.SubItems.Add(inspection.getInspectionDate().ToShortDateString());
item.SubItems.Add(inspection.getHouse().getAddress().ToString());
item.SubItems.Add(inspection.getHouse().getValue().ToString("C"));
listView1.Items.Add(item);
}
That code produces the following output in the ListView (of course depending how many items you have in the List Collection):
Basically the first column is a listviewitem containing many subitems (other columns). It may seem strange but listview is very flexible, you could even build a windows-like file explorer with it!
I've refined this using an extension method on the ListViewItemsCollection. In my opinion it makes the calling code more concise and also promotes more general reuse.
internal static class ListViewItemCollectionExtender
{
internal static void AddWithTextAndSubItems(
this ListView.ListViewItemCollection col,
string text, params string[] subItems)
{
var item = new ListViewItem(text);
foreach (var subItem in subItems)
{
item.SubItems.Add(subItem);
}
col.Add(item);
}
}
Calling the AddWithTextAndSubItems looks like this:
// can have many sub items as it's string array
myListViewControl.Items.AddWithTextAndSubItems("Text", "Sub Item 1", "Sub Item 2");
Hope this helps!
I think the quickest/neatest way to do this:
For each class have string[] obj.ToListViewItem() method and then do this:
foreach(var item in personList)
{
listView1.Items.Add(new ListViewItem(item.ToListViewItem()));
}
Here is an example definition
public class Person
{
public string Name { get; set; }
public string Address { get; set; }
public DateTime DOB { get; set; }
public uint ID { get; set; }
public string[] ToListViewItem()
{
return new string[] {
ID.ToString("000000"),
Name,
Address,
DOB.ToShortDateString()
};
}
}
As an added bonus you can have a static method that returns ColumnHeader[] list for setting up the listview columns with
listView1.Columns.AddRange(Person.ListViewHeaders());
Create a listview item
ListViewItem item1 = new ListViewItem("sdasdasdasd", 0)
item1.SubItems.Add("asdasdasd")
ListViewItem item = new ListViewItem();
item.Text = "fdfdfd";
item.SubItems.Add ("melp");
listView.Items.Add(item);
add:
.SubItems.Add("asdasdasd");
to the last line of your code so it will look like this in the end.
listView1.Items.Add("sdasdasdasd").SubItems.Add("asdasdasd");
Generally:
ListViewItem item = new ListViewItem("Column1Text")
{ Tag = optionalRefToSourceObject };
item.SubItems.Add("Column2Text");
item.SubItems.Add("Column3Text");
myListView.Items.Add(item);
Great !! It has helped me a lot. I used to do the same using VB6 but now it is completely different.
we should add this
listView1.View = System.Windows.Forms.View.Details;
listView1.GridLines = true;
listView1.FullRowSelect = true;