How can I add rows to a data grid view using a separate form? When I'm trying to pass it like this
private void btnDodajPrzychod_Click(object sender, EventArgs e)
{
formMain.gridPrzychody.Rows.Add("123");
this.Close();
}
it says that an object reference is required for the non-static field method or property "formMain.gridPrzychody".
How can I fix it? Thanks
When you calling the new Form, you must pass a handler to access the gridView from previous form. the handler could be the first form object or the gridview object.
for example:
FormNew fm = new FormNew(this.gridPrzychody);
then in the new form get and store the handler. when ever you want, you can use it then.
GridView gridView;
public FormNew(GridView gridView)
{
this.gridView = gridView;
}
Related
I am trying to do something simple here. I just want to pass selected items from a listview as a list to another window so I can bind it to combobox. Below is the code for my button that generates the list.
public void Button_Click(object sender, RoutedEventArgs e)
{
Attendees = new List<Person>();
foreach (Person attendee in lvUsers.SelectedItems)
{
Attendees.Add(attendee);
}
this.Close();
}
How do I pass this list to another window and bind it please?
snap Attendees list as filed in your window like
private List<Attendee> Attendees;
then on button click assign it and when you displaying new window of other form pass to constructor like
From1 myForm = new Form1(Attendees);
This was easy enough to do I just didn't have experience at the time. what I should have done is declared a public list and referenced it from another page. Or create a user control where I can change the datacontext so it can be binded.
I have a DataGridView binded with data from a database. I need to create a Form, which has input fields for data from a single grid row.
The Form has 30+ input controls - TextBoxes, Checkboxes and NumericUpDowns.
For now I went with this approach:
Retrieve current row from the DataGridView and load values from the cells to class instance
Pass the instance to the form and manually fill the input controls
Update the database from the form, update the DataGridView
I want to improve some things:
Is there any way to quickly fill all input controls from a class instance?
Is there any way to determine which input controls have changed their values besides manually subscribing every control on an event handler?
Is there any way to improve this whole thing, e.g. do something more efficiently?
If you are already passing in a DataRow, then you could instead pass in the DataTable and something that identifies the row in that table. And maybe optionally an adapter, if you want to commit the changes immediately on form exit. Then you can create a DataView of that table. And bind each edit control to a field in that view. Something like this:
public partial class EditForm : Form
{
DataRow row = null;
DataView view;
SqlDataAdapter adapter;
public EditForm(SqlDataAdapter adapter, DataTable table, int rowId)
{
InitializeComponent();
this.adapter = adapter;
view = table.DefaultView;
view.RowFilter = $"ID = {rowId}";
if (view.Count == 0) throw new Exception("no such row");
DataRowView dvr = view[0];
row = dvr.Row;
datebox.DataBindings.Add(new Binding("Value", view, "DATE"));
stringbox.DataBindings.Add(new Binding("Text", view, "O_STRING"));
this.FormClosing += EditForm_FormClosing;
}
private void EditForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (row.RowState == DataRowState.Modified) adapter.Update(new DataRow[] { row });
}
}
The above assuming that your table has key column named ID and fields DATE and O_STRING.
This will save you the trouble of creating an intermediate custom class instance, based on that row, moving values to and from various objects and automatically sets the RowStatae in the original table.
Re: value changed indicators. Not sure if there is a really elegant way to do that. Firstly, if I had to, I would change the background (or foreground) color rather than font boldness. Setting font to bold would change the width of the content and that is usually quite annoying. Then, I would add handlers to the TextChanged events (or ValueChange events, for controls that are not text-based). You dont need to write custom handlers to each and every edit control - in the event handler, you get the object sender parameter that points to the control object. Then you can get the field name binded to that control with something like this:
private void stringbox_TextChanged(object sender, EventArgs e)
{
Control ctrl = (Control)sender;
string fieldName = ctrl.DataBindings[0].BindingMemberInfo.BindingMember;
if ((string)view[0].Row[fieldName] != ctrl.Text) ctrl.BackColor = Color.Pink;
}
That way you will only need to add a TextChanged handler once (per edit contol class), not one per every edit box you have.
I have a form (Form1) which contains a grid, bound to a DataSource via a BindingSource.
I then have a button, which once clicked opens another form (Form2) that should let a user enter new data.
I pass the BindingSource from Form1 to Form2, and the goal is that once the user "saves" his input in Form2, it'll be automatically added to Form1.
Is there a way to do this, w/o directly accessing the UI controls?
I.E -
public partial class Form2 : Form
{
BindingSource bs = new BindingSource();
public Form2(BindingSource bindingSourceFromForm1)
{
InitializeComponent();
this.bs = bindingSourceFromForm1;
}
private void button1_Click(object sender, EventArgs e)
{
DataRow dr = (this.bs.DataSource as DataTable).NewRow();
dr["Col1"] = this.textBox1.Text;
dr["Col2"] = this.textBox2.Text;
this.bs.Add(dr);
}
}
Is there a way to bind the controls on Form2 (in the example above textBox1/2) to the BindingSource, and then have it automatically add the values in textBox1 & 2?
Something like calling this.bs.Add(), where Add() knows where to take it's values without me explicitly telling it to go to the textboxes, since it's bound to the aforementioned controls?
Thanks!
If you add a BindingSource to the form designer as you would normally do, set the DataSource to the same source so you can bind the textboxes.
In the specialized constructor the following code adds a new record to the DataSource of form1, assigns the DataSource to the DataSource of the BindingeSource instance of this form and sets the position. Your new Form will enable the user the enter the values in that new object.
public Form2(BindingSource bindingSourceFromForm1)
: this()
{
bindingSourceFromForm1.AddNew();
this.bindingSource1.DataSource = bindingSourceFromForm1.DataSource;
this.bindingSource1.Position = bindingSourceFromForm1.Position;
}
If your user can cancel the operation you have to compensate for that by calling RemoveCurrent on the bindingSourceFromForm1 but I leave that as excersice as it is not clear if you want/need that.
I have a combo box populated using dataset table adapters. I have a textbox and a button next to it. Onclick of this button the textbox value is added to the database. I want to refresh my Combobox once any new entry has been made. I did my research and figured out that I will have to Create an ObservableCollection and fill it with the data from DB. But since I am using dataset all the classes for each of the table is already present.
Here is my code:
XAML
<ComboBox Name="service" SelectedValuePath="Id" DisplayMemberPath="Service" ></ComboBox>
<TextBox Name="txtTobeAdded"></TextBox>
<Button Name="add" Content="Add" Click="add_Click"></Button>
C#
public partial class Window3 : Window
{
private SqlDatatsetTableAdapters.ServicesTableAdapter tableAdapterServices = new SqlDatatsetTableAdapters.ServicesTableAdapter();
public Window3()
{
InitializeComponent();
System.Data.DataView vw = tableAdapterServices.GetData().DefaultView;
service.ItemsSource = vw;
service.SelectedIndex = 0;
}
private void add_Click(object sender, RoutedEventArgs e)
{
tableAdapterServices.InsertQuery(txtTobeAdded.Text);
}
}
your scenario : Whatever changes to the database must be reflected to the combobox..
solution 1 : just call the another form as ShowDialog() instead of Show() and as soon as the child form is closed bind the datasource of the combobox again. as u can query the database again and retrieve the data again.
solution 2 : Just have a static List and send the newly added value to the Parent form from the child form using the Parent constructor.
try:
private void add_Click(object sender, RoutedEventArgs e)
{
tableAdapterServices.InsertQuery(txtTobeAdded.Text);
service.ItemsSource = tableAdapterServices.GetData().DefaultView;;
service.SelectedIndex = 0;
}
Its a lazy solution pushing the values back into the combo box. If you would like to learn the way to do it using an observable collection you will have to look at data Binding and the MVVM design pattern. More Info Found here
i have a datagridview that show my data in columns.
what i'm trying to accomplish is that after choosing a row and pressing edit button a new form will open and split the row for the right text boxes to update the data.
the datagridview row shows different types of data: name,email,date,etc...
any idea?
Thanks in advance!
This site explains how to send data between forms, it would be as simple as selecting the right cell in the datagrid, sending that info off to the right textbox, for all of them. then sending them back. Data between forms
The basics are to create a method that can be use to get the value,
public string getTextBoxValue()
{
return TextBox.Text;
}
then you can just call the method to pass the data between the forms,
this.Text = myForm2.getTextBoxValue();
however you will be sending the values of the cells, and will be making a textbox.text equal to the return of the method
this is a basic example of the theory, giev it a try yourself to make it work for what you want it to do, if you just cant do it come back and ask for help and ill edit with the code, but only after youve tried yourself first
You can create a class, say MyDataCollection, with properties corresponding to your DataGridView columns. When you press the Edit button, create a new instance of this class, fill it with the necessary data and pass it as parameter to the EditForm's constructor.
public class MyDataCollection
{
public string Name;
public string Email;
// --
}
In your main form:
void btnEdit_Click(object sender, EventArgs e)
{
// Create the MyDataCollection instance and fill it with data from the DataGridView
MyDataCollection myData = new MyDataCollection();
myData.Name = myDataGridView.CurrentRow.Cells["Name"].Value.ToString();
myData.Email = myDataGridView.CurrentRow.Cells["Email"].Value.ToString();
// --
// Send the MyDataCollection instance to the EditForm
formEdit = new formEdit(myData);
formEdit.ShowDialog(this);
}
And the edit form should look like this:
public partial class formEdit : Form
{
// Define a MyDataCollection object to work with in **this** form
MyDataCollection myData;
public formEdit(MyDataCollection mdc)
{
InitializeComponent();
// Get the MyDataCollection instance sent as parameter
myData = mdc;
}
private void formEdit_Load(object sender, EventArgs e)
{
// and use it to show the data
textbox1.Text = myData.Name;
textbox2.Text = myData.Email;
// --
}
}
You can also forget about the MyDataCollection class and pass the entire DataGridViewRow to the formEdit's constructor.