Listview as a log file - c#

Hi. I have a Windows form application. After I do something, what I want is to put updates in the Listview. More like a log file. Here is my code:
private void Form1_Load(object sender, EventArgs e)
{
listView1.View = View.Details;
listView1.GridLines = true;
listView1.FullRowSelect = true;
//Add column header
listView1.Columns.Add("Import Status", 100);
listView1.Columns.Add("Price", 70);
listView1.Columns.Add("Date", 70);
//Add items in the listview
string[] arr = new string[4];
ListViewItem itm;
//Add first item
arr[0] = "product_1";
arr[1] = "100";
arr[2] = "10";
itm = new ListViewItem(arr);
listView1.Items.Add(itm);
//Add second item
arr[0] = "product_2";
arr[1] = "200";
arr[2] = "20";
itm = new ListViewItem(arr);
listView1.Items.Add(itm);
}
How can I Add items to the ListView without 'hardcoding' them? Any suggestions? How can I do that every Button.Click, it can add rows with some data in it?

How can I Add items to the ListView without 'hardcoding' them?
Code
private void Form1_Load(object sender, EventArgs e)
{
listView1.View = View.Details;
listView1.GridLines = true;
listView1.FullRowSelect = true;
listView1.Columns.Add("Import Status");
listView1.Columns.Add("Price");
listView1.Columns.Add("Date");
}
private void btnAdd_Click(object sender, EventArgs e)
{
ListViewItem LVI = new ListViewItem(txtstatus.Text);
LVI.SubItems.Add(txtPrice.Text);
LVI.SubItems.Add(txtDate.Text);
listView1.Items.Add(LVI);
}
UI

Globalize your these two lines to allow your access in every method of your class:
string[] arr = new string[4];
ListViewItem itm;
Now create a button click event and put your code in it:
private void button1_Click(object sender, EventArgs e)
{
arr[0] = "product_2"; //you can get these values from textboxes if you are taking input from user
arr[1] = "200";
arr[2] = "20";
itm = new ListViewItem(arr);
listView1.Items.Add(itm);
}

hi there :) you could use a datagridview instead of the listview control.
all you have to do is to define an own dataset or add a dataset control
to your project. u just need to add your three columns to a new datatable in there.
then:
add that dataset to your form, it will appear in your form code
set the datasource of the datagridview to the added dataset
now you can add new datarows to the datatable and they will appear in the datagridview automatically. the good thing is, you have to define your table layout once and the designer will generate you a custom datarow type, what you can use.
my experience told me, that this way is more comfortable than using listview. the main thing is, u can LINQ over the datatable if you want to process data from there in other
context. i used listview before, but since datagridview in combination with dataset, everything is better ;)
sincerly,
ceth

Related

Adding Items To List In Winforms

I'm trying to implement a submit button to where the user inputs their information in 3 textboxes and when they click on the submit button, the information gets stored into a list which allows me to add it to an object that I have created.
I have tried creating a temporary list, the first index seems to display fine, but I'm really struggling to understand how to add onto the list and how to make it so when they click on 'submit' again, it stores in the next index.
Every time I click on submit, it contentiously stores in the first index.
private Fleet boatOne;
private Fleet boatTwo;
private Fleet boatThree;
private Fleet boatFour;
private void BoatSubmitButton_Click(object sender, EventArgs e)
{
List<string> tempTextBox = new List<string>();
tempTextBox.Add(BoatNameTextBox.Text);
tempTextBox.Add(BoatNameTextBox.Text);
string licenseVariable = BoatLicenseTextBox.Text;
string intVariable = MaximumLoadTextBox.Text;
boatOne = new Fleet(tempTextBox[0], licenseVariable, intVariable);
BoatNameTextBox.Text = boatOne.GetboatName();
BoatLicenseTextBox.Text = boatOne.GetboatLicense();
MaximumLoadTextBox.Text = boatOne.GetmaximumLoad();
boatTwo = new Fleet(tempTextBox[1], licenseVariable, intVariable);
BoatNameTextBox.Text = boatTwo.GetboatName();
BoatLicenseTextBox.Text = boatTwo.GetboatLicense();
MaximumLoadTextBox.Text = boatTwo.GetmaximumLoad();
BoatNameTextBox.Text = "";
BoatLicenseTextBox.Text = "";
MaximumLoadTextBox.Text = "";
Also, when I click on the submit button, not only do I want it storing the information into an object, but I want the object to display properly into my DataGridView.
DataTable dt2 = new DataTable();
dt2.Columns.Add("Boat Name");
dt2.Columns.Add("License Number");
dt2.Columns.Add("Maximum Load");
dt2.Rows.Add(new object[] { boatOne.GetboatName(), boatOne.GetboatLicense(), boatOne.GetmaximumLoad() });
dt2.Rows.Add(new object[] { boatTwo.GetboatName(), boatTwo.GetboatLicense(), boatTwo.GetmaximumLoad() });
dt2.Rows.Add(new object[] { boatThree });
dt2.Rows.Add(new object[] { boatFour });
BoatDataGridView.DataSource = dt2;
BoatDataGridView.CellBorderStyle = DataGridViewCellBorderStyle.None;
BoatDataGridView.RowHeadersVisible = false;
BoatDataGridView.AutoResizeColumns();
BoatDataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
FishDataGridView.AutoResizeColumns();
FishDataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
This can be done with nearly no code (written by you I mean) at all:
right click your project in solution explorer
add a new item
make it a DataSet, give it a suitable name
on the design surface for the dataset right click and choose Add New.. DataTable
name it Fleet (personally I would name it Boat but..)
right click it and add columns for name, license number etc
save the set
open the forms designer
show the Data sources window (view menu >> other windows >> data sources)
expand the datset node
drag the Fleet node into the forms designer
expand the fleet node
drag all the children of it to the forms designer too
You now have text boxes and a grid, data bound to the same dataset. You also have a menu bar type thing with an add button and some navigators etc
Run the program. You can either type in the grid cells or the text boxes. You can use the nav buttons or click different rows in the grid to change the current row
If you want to add elements to a list and then update a DataGridView, then you don't need the individual Fleet elements. Just one List(Of Fleet)
private List<Fleet> myBoats = new List<Fleet>();
....
private void BoatSubmitButton_Click(object sender, EventArgs e)
{
Fleet boat = new Fleet(BoatNameTextBox.Text, BoatLicenseTextBox.Text, MaximumLoadTextBox.Text;);
myBoats.Add(boat);
BoatDataGridView.DataSource = null;
BoatDataGridView.DataSource = myBoats;
BoatNameTextBox.Text = "";
BoatLicenseTextBox.Text = "";
MaximumLoadTextBox.Text = "";
}
However, you could use a simplified approach if you bind your DataGridView to a BindingList instead of a simple List. The BindingList object has the ability to automatically refresh the binded object
public void Form1_Load(object sender, EventArgs e)
{
BoatDataGridView.DataSource = new BindingList<Fleet>();
}
private void BoatSubmitButton_Click(object sender, EventArgs e)
{
Fleet boat = new Fleet(BoatNameTextBox.Text, BoatLicenseTextBox.Text, MaximumLoadTextBox.Text;);
BindingList<Fleet> bs = BoatDataGridView.DataSource as BindingList<Fleet>;
bs.Add(boat);
BoatNameTextBox.Text = "";
BoatLicenseTextBox.Text = "";
MaximumLoadTextBox.Text = "";
}
List<Fleet> boatList = new List<Fleet>();
DataTable dt2 = new DataTable();
private Fleet currentBoat;
private int boats = 0;
private void BoatSubmitButton_Click(object sender, EventArgs e)
{
string licenseVariable = BoatLicenseTextBox.Text;
string intVariable = MaximumLoadTextBox.Text;
if (BoatNameTextBox.Text == "")
{
MessageBox.Show("Please Input Name", "ERROR", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
else
{
boatList.Add(new Fleet(BoatNameTextBox.Text, licenseVariable,
intVariable));
currentBoat = boatList[boats];
dt2.Rows.Add(new object[] { currentBoat.GetboatName(),
currentBoat.GetboatLicense(), currentBoat.GetmaximumLoad() });
}
BoatNameTextBox.Text = "";
BoatLicenseTextBox.Text = "";
MaximumLoadTextBox.Text = "";
boats++;
}

Change visible state of DataGridView only given its name

I have a form application where multiple DataGridView objects are to be displayed (but not at once). They should be created on top of each other and it should then be possible to toggle the displayed DataGridView using a ComboBox.
I have a function which should create new DataGridView every time its called and then adds the name to the ComboBox:
private void readCSV(string DBname)
{
DataGridView tagDBname = new DataGridView();
tagDBname.Location = new System.Drawing.Point(24, 260);
tagDBname.Name = DBname;
tagDBname.Size = new System.Drawing.Size(551, 217);
tagDBname.TabIndex = 6;
tagDBname.Columns.Add("Column1", "Col1");
tagDBname.Columns.Add("Column2", "Col2");
tagDBname.Visible = false;
comboBoxTag.Items.Add(DBname);
}
Then I would like to change the visibility state of a DataGridView given the selected name from the ComboBox. This should be done in the function called when the index changes:
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
DataGridView tagDatabase = ? // Here the DataGridView should be selected given the name "selectedTagDB"
tagDatabase.Visible = true;
}
In the above, I do not know how to assign the DataGridView only given its name. Any help would be appreciated - even if it means that the selected approach is inappropriate of what I am trying to achieve. If the question is answered elsewhere, feel free to guide me in the right direction :)
I would store the gridviews in a dictionary by using the DB name as key;
private readonly Dictionary<string, DataGridView> _tagDBs =
new Dictionary<string, DataGridView>();
private void readCSV(string DBname)
{
DataGridView tagDBname = new DataGridView();
// Add the gridview to the dictionary.
_tagDBs.Add(DBname, tagDBname);
tagDBname.Name = DBname;
tagDBname.Location = new System.Drawing.Point(24, 260);
tagDBname.Size = new System.Drawing.Size(551, 217);
tagDBname.TabIndex = 6;
tagDBname.Columns.Add("Column1", "Col1");
tagDBname.Columns.Add("Column2", "Col2");
tagDBname.Visible = false;
this.Controls.Add(tagDBname); // Add the gridview to the form ot to a control.
comboBoxTag.Items.Add(DBname);
}
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
foreach (DataGridView dgv in _tagDBs.Values) {
dgv.Visible = dgv.Name == selectedTagDB; // Hide all gridviews except the selected one.
}
}
If you need to do something with the selected gridview, you can get it with:
if (_tagDBs.TryGetValue(selectedTagDB, out DataGridView tagDatabase)) {
// do something with tagDatabase.
}
Note: you must add the gridview to the form or to a container control on the form. E.g.
this.Controls.Add(tagDBname);
You can loop through all DataGridViews of the form to display the expected one using its name, while hidding the others ones.
This solution isn't pretty but works
private void ShowOneDataGridViewAndHideOthers(string name)
{
foreach (var DGV in this.Controls.OfType<DataGridView>())
{
DGV.Visible = DGV.Name == name;
}
}
And call it this way :
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
ShowOneDataGridViewAndHideOthers(selectedTagDB);
}
The method can be made a bit more generic this way :
private void ShowOneControlAndHideOthers<T>(string name, Control controls) where T : Control
{
foreach (var control in controls.Controls.OfType<T>())
{
control.Visible = control.Name == name;
}
}
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
ShowOneControlAndHideOthers<DataGridView>(selectedTagDB, this);
}

How to remove item from listbox and have changes reflected in entity

I'm trying to bind an entity to a listbox, and when I remove something from the entity, I want it to be reflected in the listbox.
Here is a code snippet:
SportsClubEntities spe = new SportsClubEntities
BindingSource bs = new BindingSource();
var stm =
from xyz in spe.SomeEntity where xyz.prop == 66
select new { Name = xyz.name, rec = xyz }
bs.DataSource = stm.ToList();
ListBox.DataSource = bs;
ListBox.DisplayMember = "Name";
ListBox.ValueMember = "rec";
I have a button, which when I click, I want it to remove the selected item in the listbox, but more than that, I want it to remove the item from the underlying entity. ie: when xyz is selected and removed from the listbox, I want xyz removed from spe.
If I do a bs.Remove(item) that removes the item from the listbox (when I then call bs.ResetBindings(), but it doesn't update the entity (spe.SomeEntity). Initially, I thought it would, but then I realised that the LINQ is a query, returning some results.
When I click the remove button, I can do spe.SomeEntity.Remove(item), but then the listbox doesn't get updated.
Is there a way I can perform the remove on just one of the them, and have both updated?
Am I doing this completely wrong? Is there some sort of 'standard' way to do this sort of thing?
I can't bind spe.SomeEntity.ToList() to the listbox directly, because I need a subset of the records in the entity.
Appreciate any help, I'm still learning.
Here's how you can do it:
private void Form1_Load(object sender, EventArgs e)
{
list1 = new List<Person>();
using (SportsClubEntities spe = new SportsClubEntities())
{
list1 = (from p in spe.People
select p).ToList();
}
bs = new BindingSource();
bs.DataSource = list1;
listBox1.DataSource = bs;
listBox1.DisplayMember = "FirstName";
}
private void button1_Click(object sender, EventArgs e)
{
Person p1 = (Person)listBox1.SelectedItem;
list1.Remove((Person)listBox1.SelectedItem);
bs.ResetBindings(false);
using (SportsClubEntities spe = new SportsClubEntities())
{
Person p2 = (from p in spe.People
where p.BusinessEntityID == p1.BusinessEntityID
select p).FirstOrDefault();
spe.People.Remove(p2);
spe.SaveChanges();
}
}
Removing a guy named "Jossef":

Why am I getting Stale Data in my databound ComboBox?

I have a form with 2 databound listboxes and two databound comboboxes. I'm using typed datasets. The controls are bound to a pair of tables with the following schema and data from this schema. One listbox and one comboBox are bound to the bar table; the other listbox and comboBox are bound to the foo table.
When the SelectedIndexChanged Event fires for the foo listBox I get the current value for the Selected Text in the Bar listBox and comboBox.
However, when I use the foo comboBox and try to access the barComboBox.SelectedText inside the FooComboBox_SelectedIndexChanged event I get the previously selected value from SelectedText instead of the new value. The BarListBox.Selected gives me the current value.
Note that I use the FooListBox to do the selection, both event handlers function as expected.
Can anyone explain what's going on here and how to work around this?
Form Screenshot w/sample data:
The dataset designer:
The form1.cs code:
//Standard using statements and namespace info
public partial class Form1 : Form
{
//Loading DataSets and initializing here
private void FooListBox_SelectedIndexChanged(object sender, EventArgs e)
{
Console.WriteLine("The value in the bar ListBox is {0}", barListBox.Text);
}
private void FooComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
Console.WriteLine("The value in the bar comboBox is {0}", barComboBox.Text);
}
}
I didn't find any behaviour as you Explained.
pleas check this code , Please do correct me reproduced code is wrong.
I have used Combo Box items and ListBox items are added in FormLoad as DataSource from Some webServiceMethod
in Form1.Designer.cs
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.listBox1 = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// comboBox1
//
this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(32, 55);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(188, 21);
this.comboBox1.TabIndex = 0;
this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
//
// listBox1
//
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point(261, 55);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(255, 95);
this.listBox1.TabIndex = 1;
this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
*in Form1.cs*
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
MessageBox.Show("The value in the bar comboBox is "+ comboBox1.Text);
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
MessageBox.Show("The value in the bar comboBox is "+ listBox1.Text);
}
private void Form1_Load(object sender, EventArgs e)
{
WebServiceRef.CM_ServiceSoapClient soapClient = new WebServiceRef.CM_ServiceSoapClient();
comboBox1.DataSource = soapClient.GetAllCategories();
listBox1.DataSource = soapClient.GetAllCategories();
}
I have changed the Data According to DataSource form WebService Method, Still I didn't find any issues as you exaplined your beahaviour.

Add item to Listview control

I have a listview in c# with three columns and the view is details. I need to add a item to each specific column but I am having a hard time with this. I have tried several things. Here is what I got so far. Thanks for any help in advance.
// Add the pet to our listview
ListViewItem lvi = new ListViewItem();
lvi.SubItems.Add(pet.Name);
lvi.SubItems.Add(pet.Type);
lvi.SubItems.Add(pet.Age);
listView.Items.Add(lvi);
I have done it like this and it seems to work:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string[] row = { textBox1.Text, textBox2.Text, textBox3.Text };
var listViewItem = new ListViewItem(row);
listView1.Items.Add(listViewItem);
}
}
The first column actually refers to Text Field:
// Add the pet to our listview
ListViewItem lvi = new ListViewItem();
lvi.text = pet.Name;
lvi.SubItems.Add(pet.Type);
lvi.SubItems.Add(pet.Age);
listView.Items.Add(lvi);
Or you can use the Constructor
ListViewItem lvi = new ListViewItem(pet.Name);
lvi.SubItems.Add(pet.Type);
....
Add items:
arr[0] = "product_1";
arr[1] = "100";
arr[2] = "10";
itm = new ListViewItem(arr);
listView1.Items.Add(itm);
Retrieve items:
productName = listView1.SelectedItems[0].SubItems[0].Text;
price = listView1.SelectedItems[0].SubItems[1].Text;
quantity = listView1.SelectedItems[0].SubItems[2].Text;
source code
Simple one, just do like this..
ListViewItem lvi = new ListViewItem(pet.Name);
lvi.SubItems.Add(pet.Type);
lvi.SubItems.Add(pet.Age);
listView.Items.Add(lvi);
Very Simple
private void button1_Click(object sender, EventArgs e)
{
ListViewItem item = new ListViewItem();
item.SubItems.Add(textBox2.Text);
item.SubItems.Add(textBox3.Text);
item.SubItems.Add(textBox4.Text);
listView1.Items.Add(item);
textBox2.Clear();
textBox3.Clear();
textBox4.Clear();
}
You can also Do this stuff...
ListViewItem item = new ListViewItem();
item.SubItems.Add("Santosh");
item.SubItems.Add("26");
item.SubItems.Add("India");
The ListView control uses the Items collection to add items to listview in the control and is able to customize items.

Categories