Listviews in C# - c#

string title = HardwareInfo.GetComputerName().ToString();
TabPage myTabPage = new TabPage(title);
// tabControl1.TabPages.Add(myTabPage);
// Create Column Headers
ListView listView2 = new ListView();
ColumnHeader columnA = new ColumnHeader();
columnA.Text = "adsasd";
columnA.Width = 185;
columnA.TextAlign = HorizontalAlignment.Left;
ColumnHeader columnB = new ColumnHeader();
columnB.Text = "asd";
columnB.Width = 185;
columnB.TextAlign = HorizontalAlignment.Left;
ColumnHeader columnC = new ColumnHeader();
columnC.Text = "asdasd";
columnC.Width = 185;
columnC.TextAlign = HorizontalAlignment.Left;
ColumnHeader columnD = new ColumnHeader();
columnD.Text = "xx";
columnD.Width = 185;
columnD.TextAlign = HorizontalAlignment.Left;
// Add columns to the ListView:
listView2.Columns.Add(columnA);
listView2.Columns.Add(columnB);
listView2.Columns.Add(columnC);
listView2.Columns.Add(columnD);
listView2.Size = new Size(800, 300);
listView2.Location = new Point(0, 0);
listView2.GridLines = true;
listView2.View = View.Details;
Here I have a copy of some of my Code, and what I am looking to do is get a list of computers on my next work, then create tabs for each computer. I have that part done perfectly fine, but the issue I am having is that, it creates the listviews with the same NAME and that is causing an obvious problem when I try and add information to those specific list views. I was wondering, how would I go about giving each listview a name of the computer for example. As you can see for my tabs I can do that, but when it comes to the list views, if i try and do the same type of assign a string title to where it says Listview listview2 It wont let me compile. I'm new to programming and I apologize if this is obvious. Thank you.

It sounds like you want to create a List<ListView> and add your listviews to it.
Depending on how you use it, you may want a dictionary instead.

If i understand the question what you want is the name variable, in this case
listView2.name = <name of listview2>
http://msdn.microsoft.com/en-us/library/system.windows.forms.listview_members(v=vs.71)
But i think you should look into using functions with a returntype of columns for those column constructor parts.

You want the to make the variable that stores the listview part of a dictionary, this way you can look up the different computers by their name, or whatever string you desire
Dictionary<string, ListView>
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
You could use a List if you don't need the lookup portion of the dictionary, but is fine with using integers as with an array
List<ListView>
http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx

Related

Edit listview item based on click_event c#

i have created a listview
ListView ListView1 = new ListView();
ListView1.Location = new System.Drawing.Point(12, 12);
ListView1.Name = "ListView1";
ListView1.Size = new System.Drawing.Size(280, 300);
ListView1.BackColor = System.Drawing.Color.White;
ListView1.ForeColor = System.Drawing.Color.Black;
ListView1.View = View.Details;
ListView1.GridLines = true;
ListView1.FullRowSelect = true;
ListView1.Columns.Add("ProductName", 100);
ListView1.Columns.Add("Quantity", 100);
ListView1.Columns.Add("Price", 100);
and i add items to it using the following code :
b.Click += (s, e) => {
string[] arr = new string[4];
ListViewItem itm;
arr[0] = b.Text;
arr[1] = x.ToString();
arr[2] = price;
itm = new ListViewItem(arr);
ListView1.Items.Add(itm);
x++;
};
b is an auto generated button, what i want to achieve is simple the variable x will increment with value 1 everytime i click on the button b, and x indicate the Quantity.
What i want:
when ever i click on the button b, the Quantity will change for the current item that has the Column["Productname"]=b.Text
What im getting:
the Quantity change but the item gets reinserted so i want to check if the item does exist first(based on Column["Productname"]) and if it does w the Quantity gets incremented by 1.
image_to_help_understand
More details: im sorry if this is getting too long, but im simply having a number of auto generated buttons and every button represents a product, when the user click on a product it gets added to the list ( to buy it later) and if the client clicks the same product n times, the Quantity should became Quantity=n without the item being added another time. thanks all and sorry for the long post.
Poking values into the UI is not a good design. I have these changes from my previous comments. Use a BindingList, public class Product : INotifyPropertyChanged, and replace the ListView with a DataGridView. This just makes life a whole lot easier and the code so simple. Creating ListBoxItems on your own is NOT a good way of doing things.
BTW: to find a product you just use a LINQ query on the ProductCollection. No searching the UI.

Add more items to same Row and same column in listview

I know how to add/delete items but I don't know how to add more items to the same field (same row and same column). I want whenever I click a button, an item is added to same selected row but not to new row in the listView.
I uploaded a photo you can check to see what I exactly mean.
Consider looking at ObjectListView or DataGridView instead of what you are currently. It may be more flexible to your needs.
Your question is somewhat unclear. Clearly you are using listView and you have columns and rows resulting in a cell / box / grid location. I gather that, after its initial creation, you wish to append or alter the data at that location.
To get to the point: Multi-line text within a given 'cell' is not supported (as best I can tell). The picture you have shown is likely a custom object or something similar to a listView, but different (such as a ObjectListView). Or perhaps a picture.
listView2.Items[0].SubItems[4].Text = "123\nabc"; //Doesn't add a proper newline like a normal string
listView2.Items[0].SubItems[4].Text = "123\rabc"; //Doesn't add a proper return carriage like a normal string
listView2.Items[0].SubItems[4].Text = "123\r\nabc"; //Doesn't add a proper newline like a normal string
I am assuming you are using the details view
listView1.View = View.Details;
First adding your headers, listView1.Columns.Add(text, width);
listView1.Columns.Add(First Name", 50);
listView1.Columns.Add("Middle Name", 100);
listView1.Columns.Add("Last Name", 100);
You then add data to the listView. However, this is not done directly. You build a listViewITEM then add that item to the list view.
string[] row = new string[3];
row[0] = "john";
row[1] = "someone";
row[2] = "doe";
ListViewItem lvi = new ListViewItem(row);
listView1.Items.Add(item);
listView1.SelectedItems[#].SubItems[#].Text = "string" + "\n" + "string2";
CrazyPaste suggested adding a row, which could be practical and is something you often see with listViews.
However, If you choose to add or "redo" the rows, be sure to remove any old information before inputting new information to avoid duplicates.
Taken from the popup within visual studio 2013 pro
listView1.Items.RemoveAt(int index)
listView1.Items.Insert(int index, string key, string text, int imageIndex)
OR
listView1.Items.Clear(); //Clears all items
then
//Add populate logic here
Two arrays or a multidimensional array in a loop would be effective if you wish to populate the listview in that manner.
To achieve this programmatically, you could...
listView2 = new ListView();
listView2.View = View.Details;
listView2.Location = new Point(50, 50);
listView2.Size = new Size(400, 100);
this.Controls.Add(listView2);
listView2.Columns.Add("AAA");
listView2.Columns.Add("BBB");
listView2.Columns.Add("CCC");
listView2.Columns.Add("DDD");
listView2.Columns.Add("EEE");
ListViewItem item1 = new ListViewItem();
item1.Text = "0"; //The way to properly set the first piece of a data in a row is with .Text
item1.SubItems.Add("1"); //all other row items are then done with .SubItems
item1.SubItems.Add("2");
item1.SubItems.Add("3");
item1.SubItems.Add("");
item1.SubItems.Add("");
ListViewItem item2 = new ListViewItem();
item2.Text = "00";
item2.SubItems.Add("11");
item2.SubItems.Add("22");
item2.SubItems.Add("33");
item2.SubItems.Add("");
item2.SubItems.Add("");
ListViewItem item3 = new ListViewItem();
item3.Text = "000";
item3.SubItems.Add("111");
item3.SubItems.Add("222");
item3.SubItems.Add("333");
item3.SubItems.Add("");
item3.SubItems.Add("");
//item1.SubItems.Clear();
//item1.SubItems.RemoveAt(1);
listView2.Items.Add(item1);
listView2.Items.Add(item2);
listView2.Items.Add(item3);
//listView2.Items.Insert(2, item1); //0 here is the row. Increasing the number, changes which row you are writing data across
listView2.Items[0].SubItems[4].Text = "123\rabc";
To 'update' the information:
listView1.Items.Clear();
listView1.Items.Add(item1);
listView1.Items.Add(item2);
...etc
NOTES:
I was not able to get .Insert to work with subitems.
If you already inserted a listViewItem, You cannot insert an item
without first removing it
SubItems are not automatically created to fill empty space. Commands like 'listView2.Items[0].SubItems[4].Text' will not work with null/non-existent SubItems
I don't have much to go on. But this adds a new row:
string[] row = { "1", "snack", "2.50" };
var listViewItem = new ListViewItem(row);
listView1.Items.Add(listViewItem);
Here's a post discussing how to update an existing listitem:
C#: How do you edit items and subitems in a listview?
Ok. after I searched the internet for ages, it turned out that listView does not support text wrap. so instead I used DataGridView. thank you for your help

The difference between ListBox.DataSource collection versus ListBox.Items?

I am dynamically creating a Winforms multi-select ListBox and adding it into a flowpanel control. I bind a datasource from an object I created and verified that the DataSource has does in fact have approximately 14 elements. When I do a listBox.SetSelected(0, true) I get an System.ArgumentOutOfRangeException error thrown.
I have determined the problem is that while the DataSource has 14 elements, the Item collection has none (0) and is therefore throwing the exception. My question is why are these two different from one another, and why would I not simply do a foreach item in datasource add to the item collection?
The following is the code I have so far:
case InsertableItemParameter.ParameterType.ListBox:
//note: two-way bindings are not possible with multiple-select listboxes
Label lblListBox = new Label();
lblListBox.Text = param.DisplayText;
ListBox listBox = new ListBox();
listBox.DataSource = param.Values;
listBox.DisplayMember = "Value";
listBox.SelectionMode = SelectionMode.MultiExtended;
listBox.Size = new System.Drawing.Size(flowPanel.Size.Width - lblListBox.Size.Width - 10, 100);
listBox.SetSelected(0, true); //will throw argument out of range exception here!
listBox.SetSelected(1, true);
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox);
flowPanel.SetFlowBreak(listBox, true);
break;
Below is an alternative solution I attempted and worked, but again why would I use DataSource versus Items collection?
case InsertableItemParameter.ParameterType.ListBox:
//note: two-way bindings are not possible with multiple-select listboxes
Label lblListBox = new Label();
lblListBox.Text = param.DisplayText;
ListBox listBox = new ListBox();
//listBox.DataSource = param.Values;
listBox.DisplayMember = "Value";
listBox.SelectionMode = SelectionMode.MultiExtended;
listBox.Size = new System.Drawing.Size(flowPanel.Size.Width - lblListBox.Size.Width - 10, 100);
listBox.BeginUpdate();
foreach (String paramater in param.Values)
{
listBox.Items.Add(paramater);
}
listBox.EndUpdate();
listBox.SetSelected(0, true);
listBox.SetSelected(1, true);
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox);
flowPanel.SetFlowBreak(listBox, true);
break;
ANSWER: Thanks for all the responses. The issue here is visibility and win-form rendering. While the difference between DataSource and Items collections were not really addressed save a few people, the true source of my problem was resolved by calling the SetSelected() method after the form was done drawing. This causes a lot of problems in the design of my application which I have to resolve, but this is was the problem. See the reply I marked as the answer.
Your problem probably lies elsewhere, because this code works fine:
string[] ds = {"123","321"};
listBox1.DataSource = ds;
listBox1.SetSelected(1, true);
MessageBox.Show(listBox1.Items.Count.ToString()); //returns 2
Tested in a brand new C# project with a listBox1 put on the form, and the above code sitting in Form_Load.
EDIT: I did not realize that creating a ListBox in runtime could make a difference, and especially because it matters when to set selected items. This code works:
string[] ds = { "123", "321" };
ListBox lst = new ListBox();
lst.DataSource = ds;
lst.Size = new Size(100,100);
this.Controls.Add(lst);
//make sure to call SetSelected after adding the ListBox to the parent
lst.SetSelected(1, true);
Thanks to #Brad for pointing this out. So back on the original question, replace this:
listBox.SetSelected(0, true);
listBox.SetSelected(1, true);
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox);
with this:
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox);
listBox.SetSelected(0, true);
listBox.SetSelected(1, true);
And it should work.
You have two options of how to get data to be available in a ListBox. You can set the DataSource or you can add the items manually via listBox.Items.Add(paramater). You cannot do both because they will step on each other hence your error
...cannot add items to the Item collection when DataSource is set.
Items From MSDN
This property enables you to obtain a reference to the list of items that are currently stored in the ListBox. With this reference, you can add items, remove items, and obtain a count of the items in the collection. For more information about the tasks that can be performed with the item collection, see the ListBox.ObjectCollection class reference topics.
Datasource From MSDN
An object that implements the IList or IListSource interfaces, such as a DataSet or an Array. The default is null
I'm not an expert on this matter, but from what I read it appears that Items allows you to add/modify the contents in the list whereas Datasource retrieves and sets the content.
The Items collection is populated from the DataSource only when the Control is visible. since you create your control dynamically, it is not added to the parent control and therefore not visible. Therefore you first need to have a Control that is visible on the screen. In your code you set DataSource and then set the selected items before your Control is visible on the FlowChart since it isn't added to the Parent control. You should change the sequence of the statements. You should add the listBox to the FlowPanel which will populate Items collection from the DataSource upon which you can execute SetSelected() method. Try this and note the changed order of the execution of your initial code:
ListBox listBox = new ListBox();
listBox.DataSource = param.Values;
listBox.DisplayMember = "Value";
listBox.SelectionMode = SelectionMode.MultiExtended;
listBox.Size = new System.Drawing.Size(flowPanel.Size.Width - lblListBox.Size.Width - 10, 100);
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox); //notice that you first add the listBox to the flowChart
listBox.SetSelected(0, true); //and then you have items in the Items collection which you can select
listBox.SetSelected(1, true);
Im not sure why there are two different Collections. The Items property seems more simple.
I found the reason for the exception:
apparently you have to do things in a specific order, like this:
//init the listbox
var listBox1 = new ListBox();
listBox1.Location = new System.Drawing.Point(122, 61);
listBox1.Size = new System.Drawing.Size(205, 147);
listBox1.SelectionMode = SelectionMode.MultiExtended;
Controls.Add(listBox1); //<-- point of interest
//then set the DataSource
listBox1.DataSource = lst;
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "Age";
//then set the selected values
listBox1.SetSelected(0, true);
listBox1.SetSelected(1, true);
My Test class look like this:
public class Test
{
private static Random r = new Random();
public Test (string name)
{
Name = name;
Age = r.Next(16, 45);
}
public string Name { get; set; }
public int Age{ get; set; }
}
And lst is declared like this:
var lst = new List<Test>()
{
new Test("jens"),
new Test("Tom"),
new Test("John"),
new Test("Don"),
new Test("Jenny"),
};

Binding one ListItem to multiple dropdown in .NET Form

Maybe this is a very simple question for you .NET guys but since I come from a MFC C++ dev teams, this behavior all got our dev team wondering what was going on. (In MFC, when we create a dropdown datasource, the source is shared but the value of each dropdown is not affected)
It's a very simple situation. I have 3 dropdownlist in my form that ask for streets. The street you are on and the others 2 closest streets. Each of these dropdownlist have the same datasource. So what we did is that (by the way ComboList is just a class that inherit ListItem with some more functions)
//Combo Street
ComboList cboNomRue = new ComboList();
Tools.GetCombo(cboNomRue, Tools.ComboTypeRt.RT_NOM_RUE, true, true);
ddlNomRue.DisplayMember = "Numero";
ddlNomRue.ValueMember = "ID";
ddlNomRue.DataSource = cboNomRue;
//Combo Street From
ddlDe.DisplayMember = "Numero";
ddlDe.ValueMember = "ID";
ddlDe.DataSource = cboNomRue;
//Combo Street To
ddlA.DisplayMember = "Numero";
ddlA.ValueMember = "ID";
ddlA.DataSource = cboNomRue;
Using this code, when the user change the value in ddlNomRue, the 3 dropdownlist change to that value! So to fix that, I did that.
//Combo Street
ComboList cboNomRue = new ComboList();
Tools.GetCombo(cboNomRue, Tools.ComboTypeRt.RT_NOM_RUE, true, true);
ddlNomRue.DisplayMember = "Numero";
ddlNomRue.ValueMember = "ID";
ddlNomRue.DataSource = cboNomRue;
ComboList cboNomRue2 = new ComboList(cboNomRue);
ComboList cboNomRue3 = new ComboList(cboNomRue);
//Combo Street From
ddlDe.DisplayMember = "Numero";
ddlDe.ValueMember = "ID";
ddlDe.DataSource = cboNomRue2;
//Combo Street To
ddlA.DisplayMember = "Numero";
ddlA.ValueMember = "ID";
ddlA.DataSource = cboNomRue3;
I don't like this since it's duplicating variables when only one is really needed. Is this the good way of dealing with this situation or is there anything else I could do?
Thanks
I am not clear about the ComboList Class used by you, but if you use the List to store the item which is to be displayed in comboBox is the better option.
The way adopted by you is not good because of creating object again and again. To overcome this, use List and just call it function AsReadOnly();
Example:
List<string> Mylist = new List<string>();
Mylist.Add("salman");
Mylist.Add("khan");
Mylist.Add("yousafzai");
Mylist.Add("ranizai");
Mylist.Add("kachokhail");
this.tUsersTableAdapter.Fill(this.dbAIASDataSet.tUsers);
comboBox1.DataSource = Mylist.AsReadOnly();
comboBox1.DisplayMember = "ID";
comboBox1.ValueMember = "ID";
comboBox2.DataSource = Mylist.AsReadOnly();
comboBox2.DisplayMember = "ID";
comboBox2.ValueMember = "ID";
But if you must have to use the Object of ComboList then implement the interface icloneable in ComboList or use any other way to create a shallow copy.
The form automatically create a default BindingContext for all objects on the form that support data binding. The BindingContext allows the form to know the count and current position of the collection entries within that object. When you select an item on the first list, you change its position and since the other two controls are bound with the same BindingContext, they all change as well. To fix this behavior, simply create a different BindingContext for each control as follow:
ddlNomRue.BindingContext = new BindingContext();
ddlDe.BindingContext = new BindingContext();
ddlA.BindingContext = new BindingContext();
Now you can bind the same ComboList to all three controls and you will still get the behavior that you want.

how to bind DataTable to legend in mschart

I use excel to paint a pic as follow:
please pay attention to the area hightlight in red
my question is:
how to bind the datatable to legend in mschart?
so , except the legend color, also people can see the detail data from the legend.
or, you guys can tell is it feasible to bind in mschart?
Thanks in advance!
As far as I know there is nothing in the API that allows you to simply "bind" your DataTable to a legend.
But you should still be able to manage something like that with some code:
var l = chart1.Legends[0];
l.LegendStyle = LegendStyle.Table;
l.TableStyle = LegendTableStyle.Tall;
l.BorderColor = Color.OrangeRed;
l.Docking = Docking.Bottom;
l.LegendStyle = LegendStyle.Table;
l.HeaderSeparator = LegendSeparatorStyle.DashLine;
l.HeaderSeparatorColor = Color.Red;
var firstColumn = new LegendCellColumn();
l.ColumnType = LegendCellColumnType.SeriesSymbol;
l.CellColumns.Add(firstColumn);
var secondColumn = new LegendCellColumn();
l.ColumnType = LegendCellColumnType.Text;
secondColumn.Text = "#SER";
l.CellColumns.Add(secondColumn);
foreach (DataRow row in dt.Rows)
{
var column = new LegendCellColumn();
column.ColumnType = LegendCellColumnType.Text;
column.HeaderText = row["x"].ToString();
column.Text = "#VALY";
l.CellColumns.Add(column);
}
However, my suggestion would be to include the data in a separate control, rather than as part of the chart itself. It would be much easier to work with if you kept it in one of the .net controls that's meant for tabular data, whether you're in winforms or webforms.

Categories

Resources