DGV updates only when cell is clicked - c#

I have a WFA, at the moment it has 2 forms.
The first form contains a DataGridView, with it's data source being a list.
When the user clicks a button, this opens up form2. Within form2 I have a bubblesort algorithm which sorts the list by one of it's properties. It then passes the updates list back to form1, and sets the new datasource to the bubbledsorted updated list from form2.
Now this works, the bubblesort works. HOWEVER, the DGV on form1 doesn't update UNLESS I click on individual rows/cells of the DGV. I have to click on each one individually for them to be in their new sorted positions.
Here's the code I have:
FORM1:
//This just shows Form2
private void sortByPriority_Click(object sender, EventArgs e)
{
fm2 = new Form2();
fm2.Show();
}
//This is called by form2 to set the new datasource
public void refreshDataGrid(DataGridView p)
{
dataGridView1.DataSource = null;
dataGridView1.DataSource = p.DataSource;
}
FORM2:
private void sortPriority_Click(object sender, EventArgs e)
{
int temp = 0;
bool tempforComp;
string tempforDate = "";
string tempforDesc = "";
string tempforName = "";
for (int write = 0; write < 10; write++)
{
for (int sort = 0; sort < toDoGen.task.Count - 1; sort++)
{
if (toDoGen.task[sort].Priority > toDoGen.task[sort + 1].Priority)
{
temp = toDoGen.task[sort + 1].Priority;
tempforComp = toDoGen.task[sort + 1].Completed;
tempforDate = toDoGen.task[sort + 1].DateOfCompletion;
tempforDesc = toDoGen.task[sort + 1].Description;
tempforName = toDoGen.task[sort + 1].Name;
toDoGen.task[sort + 1].Priority = toDoGen.task[sort].Priority;
toDoGen.task[sort + 1].Completed = toDoGen.task[sort].Completed;
toDoGen.task[sort + 1].DateOfCompletion = toDoGen.task[sort].DateOfCompletion;
toDoGen.task[sort + 1].Description = toDoGen.task[sort].Description;
toDoGen.task[sort + 1].Name = toDoGen.task[sort].Name;
toDoGen.task[sort].Priority = temp;
toDoGen.task[sort].Completed = tempforComp;
toDoGen.task[sort].DateOfCompletion = tempforDate;
toDoGen.task[sort].Description = tempforDesc;
toDoGen.task[sort].Name = tempforName;
}
}
DataGrid n = new DataGrid();
n.DataSource = toDoGen.task;
refresh();
}
}
private void refresh()
{
fm1 = new Form1();
fm1.refreshDataGrid(n);
}
EDIT: updated and just to be clear - I need to use multiple forms (University Assignment), and nonetheless, it didn't update even when I had the sorting algorithm in Form1.

I'll make a simplified example that doesn't use the BubbleSort algorithm, I hope it helps:
This is the code of Form1 class. I define a StringValue class because of this: How to bind a List<string> to a DataGridView control?
public class StringValue
{
public StringValue(string s)
{
_value = s;
}
public string Value { get { return _value; } set { _value = value; } }
string _value;
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.DataSource = new List<StringValue> {
new StringValue("string1"),
new StringValue("string3"),
new StringValue("string2")
};
}
private void button1_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2(this, dataGridView1.DataSource as List<StringValue>);
form2.Show();
}
public void RefreshGrid(List<StringValue> source)
{
dataGridView1.DataSource = source;
}
}
The button click event opens Form2 and passes to it the grid view datasource. Here's Form2:
public partial class Form2 : Form
{
Form1 _form1;
List<StringValue> _source;
public Form2(Form1 form1, List<StringValue> source)
{
_form1=form1;
_source=source;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
_source = _source.OrderBy(x => x.Value).ToList();
_form1.RefreshGrid(_source);
this.Close();
}
}
After the click on the button in Form2 the DataGridView1's data source is refreshed with a sorted version, and Form2 is closed.

Related

Return the value to a grid from a button click in c# windows application

In my C# windows application from a grid cell double click I am populating a Windows Form which is used to save the payment.So after payment the populated Form should pass the id to the grid and refresh the data in the grid.
Nutshell:I need to implement this by using delegates and events as the grid values are populating from the db.Each time after payment the grid need to be refreshed.ie,Button in the second form should trigger the parent form to refresh datagrid based on the click returned value.
Screenshot attached
Form1
private void dgvLoadBalance_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
long cellValue = long.Parse(dgvLoadBalance.Rows[e.RowIndex].Cells[2].Value.ToString());
OPPaymentDatatable= commonDL.GetOpPaymentDetails(opRegId, cellValue);
opDataTable = new DataTable();
opDataTable.Columns.Add("PatientName", typeof(string));
opDataTable.Columns.Add("DoctorName", typeof(string));
opDataTable.Columns.Add("BillTypeName", typeof(string));
opDataTable.Columns.Add("OPId", typeof(string));
opDataTable.Columns.Add("OPNumber", typeof(string));
opDataTable.Rows.Add(uctrlPatientSearch1.PatientName, uctrlPatientSearch1.DoctorName, uctrlPatientSearch1.BillTypeName, uctrlPatientSearch1.OPId,uctrlPatientSearch1.OPNumber);
var settingsdt = commonBL.GetSettings();
if (settingsdt.Rows.Count > 0 && settingsdt != null)
{
Address.Add(settingsdt.Rows[1][2]);
Address.Add(settingsdt.Rows[2][2]);
Address.Add(settingsdt.Rows[3][2]);
Address.Add(settingsdt.Rows[4][2]);
Address.Add(settingsdt.Rows[5][2]);
Address.Add(settingsdt.Rows[6][2]);
Address.Add(settingsdt.Rows[7][2]);
Address.Add(settingsdt.Rows[8][2]);
}
frmPayOPBalance frmbalancepay = new frmPayOPBalance(OPPaymentDatatable, opDataTable, Address);
frmbalancepay.ShowDialog();
}
Form2
private void btnPaynBill_Click(object sender, EventArgs e)
{
if (ValidateForm())
{
BindData();
outVal = commonBL.InsertOpBalanceHistoryPayment(opPaymentModel);
if (outVal > 0)
{
var dt = commonBL.GetOpBalanceBill(opPaymentModel);
if (dt != null && dt.Rows.Count > 0)
opPaymentModel.BillNumber = long.Parse(dt.Rows[0]["BillId"].ToString());
MessageBox.Show("Balance Payment made successfully", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
particularsDt = new DataTable();
particularsDt.Columns.Add("Particulars", typeof(string));
particularsDt.Columns.Add("Rate", typeof(string));
particularsDt.Columns.Add("Amount", typeof(decimal));
particularsDt.Rows.Add("OP Balance Payment for Reciept # " + opPaymentModel.OldBillId, string.Empty, opPaymentModel.BalAmount);
BalancePaymentBillPrint objBalaPayPrint = new BalancePaymentBillPrint(opPaymentModel, Address, particularsDt);
ClearBindings();
this.Hide();
}
else
MessageBox.Show("Error found in bill entry", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
A simple way is that you can use public properties and Application.OpenForms Property to achieve it.
Here is a demo. In this example, there is a DataGridView with two columns "ID" and "Number".
First, we need to define a property to access the DataGridView instance in Form1.
public DataGridView DGV
{
get { return dataGridView1; }
set { dataGridView1 = value; }
}
Then define properties to get LabelID and TextBoxNumber in Form2.
public Label LBID
{
get { return labelID; }
set { labelID = value; }
}
public TextBox TBNum
{
get { return textBoxNumber; }
set { textBoxNumber = value; }
}
Then pass values to Form2 via related properties.
// DataGridView in Form1
private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
Form2 form2 = new Form2();
form2.LBID.Text = dataGridView1.Rows[e.RowIndex].Cells["ID"].Value.ToString();
form2.TBNum.Text = dataGridView1.Rows[e.RowIndex].Cells["Number"].Value.ToString();
form2.Show();
}
Last, we can use Application.OpenForms Property in Form2 to get the Form1 instance to modify the DataGridview.
private void btnUpdate_Click(object sender, EventArgs e)
{
Form1 form1 = (Form1)Application.OpenForms["Form1"];
form1.DGV.Rows[Convert.ToInt32(labelID.Text) - 1].Cells["Number"].Value = textBoxNumber.Text;
this.Close();
}
Test result:
Update: using delegate and event
Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//event handle method
void frm_TransfEvent(int rowindex, string value)
{
// set Number column value
dataGridView1.Rows[rowindex].Cells["Number"].Value = value;
}
private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
Form2 frm = new Form2();
// pass rowindex to form2
frm.ROWIndex = e.RowIndex;
//subscribe to event
frm.TransfEvent += frm_TransfEvent;
frm.ShowDialog();
}
}
Form2.cs
public delegate void TransfDelegate(int rowindex, string value);
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public event TransfDelegate TransfEvent;
public int ROWIndex { get; set; }
private void btnUpdate_Click(object sender, EventArgs e)
{
//trigger event
TransfEvent(ROWIndex, textBox1.Text);
this.Close();
}
}

c# how to delete and edit information from selected in listbox?

string Path = #"C:\Users\Alexander\Desktop\Adressbok\Adressbok.txt";
List<string> sökhistorik;
//Lista
List<Person> Personer = new List<Person>();
//instans
Person p1 = new Person();
public Form1()
{
InitializeComponent();
}
private void updateUI()
{
lstBox.DataSource = null;
lstBox.DataSource = Personer;
}
private void btnSpara_Click(object sender, EventArgs e)
{
p1.Namn = tbxNamn.Text;
p1.Gatuadress = tbxGatuadress.Text;
p1.Postnummer = tbxPostnummer.Text;
p1.Postort = tbxPostort.Text;
p1.Telefonnummer = tbxTelefonnummer.Text;
p1.Epost = tbxEpost.Text;
Personer.Add(p1);
updateUI();
SaveToFile();
tbxNamn.Text = "";
tbxGatuadress.Text = "";
tbxPostnummer.Text = "";
tbxPostort.Text = "";
tbxTelefonnummer.Text = "";
tbxEpost.Text = "";
}
I want to edit the selected item from listbox and then edit the information and save it again and then make a delete button and delete the whole information. How do i do it. Im using windows forms c#.
Why don''t you use BindingList instead of List?
BindingList will automatically update your UI based on your source.
Assuming Person has a ToString(),
// Bind BindingList to Listbox
public class Form1 {
BindingList<Person> personer = new BindingList<Person>();
public Form1() {
InitializeComponent();
listBox1.DataSource = personer;
}
// Remove on button click
private void button1_Click(object sender, EventArgs e)
{
if (listBox1.SelectedIndex > -1)
{
//This automatically updates your listBox
personer.RemoveAt(listBox1.SelectedIndex);
}
}
// Update on Button click
private void button2_Click(object sender, EventArgs e)
{
if (listBox1.SelectedIndex > -1)
{
Person p = personer[listBox1.SelectedIndex];
//Update person here
}
}

How to pass data from childform to parentform

I have two forms ,Form1 and Form2.
Form1 - Parent
Form2 - Child
Form1 Contains the following,
Textbox - it loads the file path,
Datagridview - it loads the file with its data,
ButtonNext -when button cliked it opens Form2,
Form2 Contains the following,
BrowseButton - it broswe for the file from the directory
Textbox - it then shows the path
ButtonFinish - it will tabes you back to Form1
*Now i want to access datagridview from Form1(Parent) from Form2(child). Now i can broswe the file on Form2 and when i click finish i can see my file path on Form1(parent) from the textbox but with no databeing loaded.
How can i load the data on Form1 into the datagridview ?
this is my code so far..
Form2.
public frmInputFile(frmMain_Page _frmMain)
{
InitializeComponent();
this._frmMain = _frmMain;
}
private void btnBrowse_Click(object sender, EventArgs e)
{
BrowseFile();
}
private void btnFinish_Click(object sender,EventArgs e)
{
_frmMain.SetFilepath(txtInputfile.Text);
_grid.Rows.Clear(); //cant get the grid from form1
string PathSelection = "";
if (txtInputfile.Text.Length > 0)
{
PathSelection = txtInputfile.Text;
}
oDataSet = new DataSet();
XmlReadMode omode = oDataSet.ReadXml(PathSelection);
for (int i = 0; i < oDataSet.Tables[2].Rows.Count; i++)
{
string comment = oDataSet.Tables["data"].Rows[i][2].ToString();
string font = Between(comment, "[Font]", "[/Font]");
string datestamp = Between(comment, "[DateStamp]", "[/DateStamp]");
string commentVal = Between(comment, "[Comment]", "[/Comment]");
string[] row = new string[] { oDataSet.Tables["data"].Rows[i][0].ToString(), oDataSet.Tables["data"].Rows[i][1].ToString(), font, datestamp, commentVal };
_grid.Rows.Add(row);
}
this.Hide();
Program._MainPage.Show();
Form1
private void btnLoadfile_Click(object sender, EventArgs e)
{
frmInputFile frmInput = new frmInputFile(this);
frmInput.Show();
}
public void SetFilepath(string Filepath)
{
txtInputfile.Text = Filepath;
}
//I dont know how i can handle the gridview here
public void Loadgrid(string LoadGrid)
{
Gridview_Input.ToString();
}
First things first. Please avoid duplicate posts.
What is the variable _grid doing here ?? Your way of passing data from one form to the other looks very strange. Nevertheless, I tried to simulate your problem and I am able to add the rows in Form1 from From2. The code listing is given below. Just a thing to note,I have added four columns in to my DataGridView in the designer. In your case you might want to add the columns as well programmatically.
public partial class Form2 : Form
{
public Form2(Form1 frm1)
{
InitializeComponent();
Form1Prop = frm1;
}
private void button1_Click(object sender, EventArgs e)
{
Form1Prop.SetFilepath("HIHI");
Form1Prop.DataGridPropGrid.Rows.Add("HIH", "KI", "LO", "PO");
}
public Form1 Form1Prop { get; set; }
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2(this);
frm2.Show();
}
public void SetFilepath(string filepath)
{
textBox1.Text = filepath;
}
public DataGridView DataGridPropGrid
{
get
{
return dataGridView1;
}
}
}
Cheers

Passing data to DataGridViews

I have text boxes on my second form and a send button which is in the code shown below.
private void button1_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
f1.PassName = richTextBox1.Text;
f1.PassLastName = richTextBox2.Text;
f1.PassAge = comboBox1.Text;
f1.PassGender = richTextBox3.Text;
f1.ShowDialog();
}
and a DataGridView on form 1 with this code
public partial class Form1 : Form
{
private string name;
private string lastName;
private string age;
private string gender;
public string PassName
{
get { return name; }
set { name = value; }
}
public string PassLastName
{
get { return lastName; }
set { lastName = value; }
}
public string PassAge
{
get { return age; }
set { age = value; }
}
public string PassGender
{
get { return gender; }
set { gender = value; }
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
int n = dataGridView1.Rows.Add();
dataGridView1.Rows[n].Cells[0].Value = name;
dataGridView1.Rows[n].Cells[1].Value = lastName;
dataGridView1.Rows[n].Cells[2].Value = age;
dataGridView1.Rows[n].Cells[3].Value = gender;
}
private void mnuExit_Click(object sender, EventArgs e) //adding the quit on the top file with caution message
{
if (MessageBox.Show("Do you really want to Quit?", "Exit", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
Application.Exit();
}
}
private void addTask_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2(); //show form2 so user can input data
f2.ShowDialog();
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
}`
This is fine if I want to send one set of data to the DataGridView, but if I add new information again then this opens a new DataGridView and stores it to another seperate DataGridView then I have two DataGridView forms. I want to put all the data onto one DataGridView and keep adding rows. So when the user clicks the add button on the first form with the DataGridView, it opens up the TextBox form which is form 2, then the user fills out the information and clicks the send button which sends the information back to the DataGridView, however this then opens up a new window with a new DataGridView. I dont want this to happen I want it to keep adding rows on the first form.
Could someone show me how to do this?
You can use ShowDialog(this) and Owner to get the parent form's property.
Form1
private void Form1_Load(object sender, EventArgs e)
{
//Move to Form1_Activated
this.Activated += new System.EventHandler(this.Form1_Activated); //connect
}
private void Form1_Activated(object sender, EventArgs e)
{
int n = dataGridView1.Rows.Add();
dataGridView1.Rows[n].Cells[0].Value = name;
dataGridView1.Rows[n].Cells[1].Value = lastName;
dataGridView1.Rows[n].Cells[2].Value = age;
dataGridView1.Rows[n].Cells[3].Value = gender;
}
private void addTask_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2(); //show form2 so user can input data
f2.ShowDialog(this);//set this form as Owner
}
Form2
private void button1_Click(object sender, EventArgs e)
{
Form1 f1 = (Form1)this.Owner;//Get the Owner form
f1.PassName = richTextBox1.Text;
f1.PassLastName = richTextBox2.Text;
f1.PassAge = comboBox1.Text;
f1.PassGender = richTextBox3.Text;
//f1.ShowDialog();
f1.Show();
this.Close();
}

Reflecting modified fields in the DataGridView

To get to my question, I need to do a little explanation first so bear with me.
This application has 2 forms. In the main form, I have a DataGridView. It is displaying data from a database table. Its DataSource is set to a DataTable object. Here is the code of the main form.
using System;
using System.Data;
using DataAccess;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
private SqlDataAccess _dataAccess = new SqlDataAccess(); //SqlDataAccess is a class written to handle database related operations
private DataTable _dataTable = null;
private void Form1_Load(object sender, EventArgs e)
{
string query = #"SELECT * FROM fEmployee";
_dataTable = _dataAccess.GetDataTable(query, null);
dgvEmployees.DataSource = _dataTable;
}
private void dataGridView1_RowHeaderMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
{
//Convert the current selected row in the DataGridView to a DataRow
DataRowView currentDataRowView = (DataRowView)dgvEmployees.CurrentRow.DataBoundItem;
DataRow dataRow = currentDataRowView.Row;
Form2 f = new Form2(dataRow);
f.ShowDialog();
}
}
}
When clicked upon the row headers of the DataGridView, a sub form will appear. This sub form acts as a place to modify the selected rows' field values. A DataRow object containing the selected row's fields is sent to the sub form's overloaded constructor. And in that form's Load event, the data contained in that DataRow will be displayed in multiple Textboxes in the sub form.
The code of the sub form.
using System;
using System.Data;
namespace WindowsFormsApplication3
{
public partial class Form2 : Form
{
private DataRow _employeeDetails = null;
private bool _isDirty = false;
public Form2(DataRow empDetails)
{
InitializeComponent();
_employeeDetails = empDetails;
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
private void Form2_Load(object sender, EventArgs e)
{
txtFName.Text = _employeeDetails["FirstName"].ToString();
txtLName.Text = _employeeDetails["LastName"].ToString();
txtAddress.Text = _employeeDetails["Address"].ToString();
txtCity.Text = _employeeDetails["City"].ToString();
txtPostalCode.Text = _employeeDetails["PostalCode"].ToString();
txtCountry.Text = _employeeDetails["Country"].ToString();
dtpDOB.Value = Convert.ToDateTime(_employeeDetails["DOB"]);
txtPhone.Text = _employeeDetails["Phone"].ToString();
txtEmail.Text = _employeeDetails["Email"].ToString();
dtpDOJ.Value = Convert.ToDateTime(_employeeDetails["DOJ"]);
txtBasicSalary.Text = _employeeDetails["BasicSalary"].ToString();
}
private void btnUpdate_Click(object sender, EventArgs e)
{
}
}
}
In the sub form, the user is able to change the values through Textboxes.
Now to my question: How can I reflect the changes done to that particular row in the sub form, in the DataGridView in the main form?
Example - I click on one row header, it opens the sub form and loads the details. I change the First Name. And when I close the sub form, that modified value should be updated in the main DataGridview.
Can anyone give some suggestions on how to do this?
I tried passing the DataRow to the sub form as a reference but that didn't work.
Try to test this approach. You have to use the DataRow[] to update the data from DataRow selected. Please try to figure it out and get some idea.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
public BindingSource bs = new BindingSource();
public DataRow[] mainDataRow;
private DataTable employee = new DataTable();
private void MainForm_Load(object sender, EventArgs e)
{
employee.Columns.Add("Id");
employee.Columns.Add("LastName");
employee.Columns.Add("FirstName");
employee.Columns.Add("MiddleName");
object[] emp1 = { "1", "Some1a", "Some1b", "Some1c" };
object[] emp2 = { "2", "Some2a", "Some2b", "Some2c" };
object[] emp3 = { "3", "Some3a", "Some3b", "Some3c" };
object[] emp4 = { "4", "Some4a", "Some4b", "Some4c" };
employee.Rows.Add(emp1);
employee.Rows.Add(emp2);
employee.Rows.Add(emp3);
employee.Rows.Add(emp4);
bs.DataSource = employee;
dataGridView1.DataSource = bs;
}
private void dataGridView1_RowHeaderMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
{
//Convert the current selected row in the DataGridView to a DataRow
DataRowView currentDataRowView = (DataRowView)dataGridView1.CurrentRow.DataBoundItem;
mainDataRow = employee.Select("Id='"+ currentDataRowView[0].ToString() + "'"); //get the primary key id
using (var f = new Form2{ dataRow = mainDataRow, Owner = this })
{
f.ShowDialog();
}
}
}
Then in Form2:
public partial class Form2: Form
{
public Form2()
{
InitializeComponent();
}
public DataRow[] dataRow;
private void Form2_Load(object sender, EventArgs e)
{
var select = dataRow[0];
lastNameTextBox.Text = select[1].ToString();
firstNameTextBox.Text = select[2].ToString();
middleNameTextBox.Text = select[3].ToString();
}
private void button1_Click(object sender, EventArgs e)
{
MainForm m = this.Owner as MainForm;
var updated = dataRow[0];
updated[1] = lastNameTextBox.Text;
updated[2] = firstNameTextBox.Text;
updated[3] = middleNameTextBox.Text;
m.mainDataRow[0] = updated;
Close();
}
}

Categories

Resources