I have a Windows Form application with a tab that contains many ComboBoxes. Every time I access this tab, I need to wait a few seconds for it to load. Is there a way to pre-load ComboBoxes while I am still using others tab of my program?
private ObjectCache cache = MemoryCache.Default;
private void LoadComboBoxData() {
var txtboxrecmedicacoes = new[] { txtboxrecmedicacoes1,
txtboxrecmedicacoes2,
txtboxrecmedicacoes3,
txtboxrecmedicacoes4,
txtboxrecmedicacoes5,
txtboxrecmedicacoes6,
txtboxrecmedicacoes7,
txtboxrecmedicacoes8};
foreach (ComboBox comboBox in txtboxrecmedicacoes)
{
string cacheKey = comboBox.Name;
if (cache.Contains(cacheKey))
{
comboBox.DataSource = cache[cacheKey];
}
else{}
}
}
This is just part your text of combobox, there is more. And I use this method on form load. I add the data to ComboBox on load of the form, the problem is when I select the specific tab. The code that I made didn't work. How can I pre-load all components of my tab?
You can use a caching technique like memory caching to avoid loading the same data multiple times
private BackgroundWorker worker = new BackgroundWorker();
private void Form1_Load(object sender, EventArgs e)
{
worker.DoWork += Worker_DoWork;
worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
worker.RunWorkerAsync();
}
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
//load combo box data here
var txtboxrecmedicacoes = new[] { txtboxrecmedicacoes1, txtboxrecmedicacoes2, txtboxrecmedicacoes3, txtboxrecmedicacoes4, txtboxrecmedicacoes5, txtboxrecmedicacoes6, txtboxrecmedicacoes7, txtboxrecmedicacoes8 };
foreach (ComboBox comboBox in txtboxrecmedicacoes)
{
string cacheKey = comboBox.Name;
if (!cache.Contains(cacheKey))
{
//load data from DB or other sources and add to cache
var data = LoadData(comboBox.Name);
cache.Add(cacheKey, data, DateTimeOffset.UtcNow.AddHours(1));
}
}
}
private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//update UI with loaded data
var txtboxrecmedicacoes = new[] { txtboxrecmedicacoes1, txtboxrecmedicacoes2, txtboxrecmedicacoes3, txtboxrecmedicacoes4, txtboxrecmedicacoes5, txtboxrecmedicacoes6, txtboxrecmedicacoes7, txtboxrecmedicacoes8 };
foreach (ComboBox comboBox in txtboxrecmedicacoes)
{
string cacheKey = comboBox.Name;
if (cache.Contains(cacheKey))
{
comboBox.DataSource = cache[cacheKey];
}
}
}
Related
I have a parent form that send a data table to a child form by Delegate.
the Delegate is executed and i have also gotten the the table on the child side.
i want to append a text into my richtextbox control to announce the user what is going on and then run a backgroundworker. but i get the STAThread Exception. i know some thing about Invoke(Delegate) and about single-Thread but i do not know how can i overcome to this cross-threading. Any help is appreciated.
The codes from Appent To RichTextBox are not execute with debugging (i know it is possible with run of the *.exe file).
//What i am doing and trying:(SetDaTableAndFileNameFn is my received Delegate)
public void SetDaTableAndFileNameFn(System.Data.DataTable DataTable)
{
//Test The Parent Has Sent And Child Has Received.
MessageBox.Show("Ruger Parent...");
dt.Clear();
dt = DataTable;
//Check whether My dt Filled Correctly.
MessageBox.Show(dt.Rows[2][2].ToString());
richTxtBxExprtr.AppendText(">>> Creating And Transferring Data To The File...");
//BGWorker.
bGWExprtrLod.WorkerReportsProgress = true;
bGWExprtrLod.RunWorkerAsync();
}
private void ExportToTxtIrrigularly(System.Data.DataTable DataTable)
{
// Using Microsoft.Office.Interop.Word.Application to export datatable.
}
private void xBtnExprt_Click(object sender, EventArgs e)
{
SaveFileDialog svFDialXls = new SaveFileDialog();
svFDialXls.Filter = "Plain text(*.txt)| *.txt";
svFDialXls.Title = "Export Data As Text";
svFDialXls.InitialDirectory = #"Desktop";
if (svFDialXls.ShowDialog() == DialogResult.OK && svFDialXls.FileName != null)
{
WordFilePath = svFDialXls.FileName.ToString();
//Fire An EventHandler In The Parent Side To Fill A datatable With A DGV.
ExportImport ExportTxFile = new ExportImport(allRowsExprt, fRowTEndExprt, fRowTEndValExprt, FTRowExprt,
FTRowValFExprt, FTRowValTExprt, allFieldsExprt, visFieldExprt, slctdFieldExprt);
OnExportTxFile(ExportTxFile);
//Filled datatable Will Send Back from parent side with theSetDaTableAndFileNameFn
}
}
private void bGWExprtrLod_DoWork(object sender, DoWorkEventArgs e)
{
this.Invoke(new Action(() =>
{
richTxtBxExprtr.AppendText(">>> Start Processing...\n>>> Copying Data Take A Little Time.\n>>> Be Patient...\n>>> Loadind Data...\n-----------------------------------------------\n");
ExportToTxtIrrigularly(dt);
}));
}
private void bGWExprtrLod_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.Invoke(new Action(() =>{richTxtBxExprtr.AppendText(">>> Line NO. [" + e.ProgressPercentage.ToString() + "] Is In Progress...\n");
richTxtBxExprtr.ScrollToCaret();
}));
}
private void bGWExprtrLod_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{this.Invoke(new Action(() => { richTxtBxExprtr.AppendText(">>> The Process Is Completed Successfuly.\n"); }));
}
the executed mthod in the BGWorker will open a savedialogbox() and then export my datatable to a text format using
Microsoft.Office.Interop.Word.Application
Not really sure what kind of setup you've got, but it will look something like this:
private BackgroundWorker bGWExprtrLod;
private void Form1_Load(object sender, EventArgs e)
{
bGWExprtrLod = new BackgroundWorker();
bGWExprtrLod.WorkerReportsProgress = true;
bGWExprtrLod.ProgressChanged += BGWExprtrLod_ProgressChanged;
bGWExprtrLod.RunWorkerCompleted += BGWExprtrLod_RunWorkerCompleted;
bGWExprtrLod.DoWork += BGWExprtrLod_DoWork;
}
public void SetDaTableAndFileNameFn(System.Data.DataTable DataTable)
{
// ... other code ...
bGWExprtrLod.RunWorkerAsync();
}
private void BGWExprtrLod_DoWork(object sender, DoWorkEventArgs e)
{
bGWExprtrLod.ReportProgress(0, ">>> Creating And Transferring Data To The File...");
// ... do some work ...
}
private void BGWExprtrLod_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
string msg = e.UserState.ToString();
richTxtBxExprtr.AppendText(msg);
}
private void BGWExprtrLod_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
richTxtBxExprtr.AppendText("Transfer Complete!");
}
** EDIT **
Start by moving the call to you export method outside the Invoke() call:
private void bGWExprtrLod_DoWork(object sender, DoWorkEventArgs e)
{
this.Invoke(new Action(() =>
{
richTxtBxExprtr.AppendText(">>> Start Processing...\n>>> Copying Data Take A Little Time.\n>>> Be Patient...\n>>> Loadind Data...\n-----------------------------------------------\n");
}));
ExportToTxtIrrigularly(dt);
}
I have this situation I want to synchronize informations in my dataGridView when I insert it on my add form like you can see on this picture.
In my Insert form on insert button I call Add form to pop up like this
private void button1_Click(object sender, EventArgs e)
{
if (addForm==null)
{
addForm = new AddForm();
}
addForm.MdiParent = this.ParentForm;
addForm.FormClosed += AddForm_FormClosed;
addForm.Show();
}
private void AddForm_FormClosed(object sender, FormClosedEventArgs e)
{
addForm = null;
}
On Add form in Accept click I insert informations and call fillDataGrid() method from Insert form to do data sync but nothing is shown data is shown just when I close Insert form and call it again does someone has susggestion how can I do this this is the first time I work with MdiContainer ?
private void buttonAccept_Click(object sender, EventArgs e)
{
if (validation())
{
Proizvod product = new Proizvod();
product.NazivProizvoda = textBoxName.Text;
product.Opis = textBoxDescription.Text;
product.SerijskiBroj = textBoxNumber.Text;
product.ZemljaPorijekla = textBoxCountry.Text;
if (pDal.insertProduct(product)==0)
{
MessageBox.Show("Informations are successfully inserted","Message");
InsertForm inForm = new InsertForm();
inForm.fillDataGrid();
}
}
}
My fillDataGrid() method and Load event of InsertForm:
public void fillDataGrid()
{
dataGridViewProducts.DataSource = null;
dataGridViewProducts.AutoGenerateColumns = false;
dataGridViewProducts.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dataGridViewProducts.ColumnCount = 3;
dataGridViewProducts.Columns[0].Name = "Product name";
dataGridViewProducts.Columns[0].DataPropertyName = "NazivProizvoda";
dataGridViewProducts.Columns[1].Name = "Country";
dataGridViewProducts.Columns[1].DataPropertyName = "ZemljaPorijekla";
dataGridViewProducts.Columns[2].Name = "Product number";
dataGridViewProducts.Columns[2].DataPropertyName = "SerijskiBroj";
dataGridViewProducts.DataSource = pDal.getAllProducts();
}
private void InsertForm_Load(object sender, EventArgs e)
{
fillDataGrid();
}
private void InsertForm_Shown(object sender, EventArgs e)
{
dataGridViewProducts.CurrentCell = null;
dataGridViewProducts.ClearSelection();
}
Currently in buttonAccept_Click code, you have created a new instance of the list form and called its FillGrid. This way you are manipulating another instance of the list form which is different from the instance which is open and you can see. You are filling a different form which you didn't show it.
Instead of creating a new instance, create a constructor for your second form which accepts a parameter of first form type. Then when you want to create a new instance of seccod form, pass the instance of the first form (this) to second Form. Then in your save button call the FillGrid method of the passed instance.
For more information about how to manipulate another form, read this post. It contains some useful options about:
Pass data to second Form when creating
Manipulate second Form after showing
Manipulate first Form from second Form
Here is some code which belong to the ListForm:
private void ShowAddForm_Click(object sender, EventArgs e)
{
if (addForm == null)
{
addForm = new AddForm(this);
addForm.MdiParent = this.ParentForm;
addForm.FormClosed += AddForm_FormClosed;
}
addForm.Show();
}
private void AddForm_FormClosed(object sender, FormClosedEventArgs e)
{
addForm = null;
}
And here is the code for AddForm
public class AddForm
{
MyListForm listForm;
public AddForm(MyListForm f)
{
InitializeComponent();
listForm = f;
}
private void SaveVutton_Click(object sender, EventArgs e)
{
//perform validation and save data
f.FillGrid();
}
}
So, I have a simple ListView that users can add information to and a delete button that is only capable of deleting one selected item at a time. I'm trying to make it so that when multiple items are selected and 'delete' is pressed it deletes those selected items instead of just one. Your help is appreciated!
Add recipient code:
private void addtoRecipients_Click(object sender, EventArgs e)
{
if (recipientEmailBox.Text != "")
{
string[] S = new string[4];
S[0] = recipientEmailBox.Text;
S[1] = recipientNameBox.Text;
S[2] = txtLocation.Text;
S[3] = txtSubject.Text;
ListViewItem I = new ListViewItem(S);
recipientBox.Items.Add(I);
UpdateNoOfEmails();
}
}
My Delete Button Code (only deletes one selection at the moment)
private void deleteEntryBTN_Click(object sender, EventArgs e)
{
try { recipientBox.Items.Remove(recipientBox.SelectedItems[0]); }
catch { }
UpdateNoOfEmails();
}
Clear All Recipients Code
private void clearBTN_Click(object sender, EventArgs e)
{
recipientBox.Items.Clear();
UpdateNoOfEmails();
}
In my case, the simplest way to do it was with a while loop. This is what my new delete button code looks like:
private void deleteEntryBTN_Click(object sender, EventArgs e)
{
try
{
while (recipientBox.SelectedItems.Count > 0)
{
recipientBox.Items.Remove(recipientBox.SelectedItems[0]);
}
}
catch { }
UpdateNoOfEmails();
}
I am attempting to write code that will display data in a datagridview based off of the size of car selected in a combo box. When this code initially runs, it defaults to economy sized, and displays the correct information in the datagridview. However, when a different size is selected in the combo box, the text boxes update correctly while the datagridview remains the same. What can I do to make it update every time the combo box is changed? I thought the code in "private void cboSize_selectionChangeCommitted()" would accomplish this, but there was no change in the output.
namespace carForm
{
public partial class Form1 : Form
{
_Cars_1_DataSet cDataSet;
BindingSource sizeBindingSource;
BindingSource vehicleBindingSource;
CarsDataClass clsCarsData;
Boolean gridInitialized;
public Form1()
{
InitializeComponent();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the '_Cars_1_DataSet.Reservations' table. You can move, or remove it, as needed.
this.reservationsTableAdapter.Fill(this._Cars_1_DataSet.Reservations);
// TODO: This line of code loads data into the '_Cars_1_DataSet.Vehicle' table. You can move, or remove it, as needed.
this.vehicleTableAdapter.Fill(this._Cars_1_DataSet.Vehicle);
// TODO: This line of code loads data into the '_Cars_1_DataSet.CarSize' table. You can move, or remove it, as needed.
this.carSizeTableAdapter.Fill(this._Cars_1_DataSet.CarSize);
clsCarsData = new CarsDataClass();
cDataSet = clsCarsData.GetDataSet();
//Binding source sizes
sizeBindingSource = new BindingSource();
sizeBindingSource.DataSource = cDataSet;
sizeBindingSource.DataMember = "CarSize";
//Binding source vehicles
vehicleBindingSource = new BindingSource();
vehicleBindingSource.DataSource = cDataSet;
vehicleBindingSource.DataMember = "Vehicle";
//Combo box
cboSize.DataSource = sizeBindingSource;
cboSize.DisplayMember = "Size";
cboSize.ValueMember = "SizeCode";
//bind other controls
txtDaily.DataBindings.Add("text", sizeBindingSource, "DailyRate");
txtMileage.DataBindings.Add("text", sizeBindingSource, "MileageRate");
//execute combo box
cboSize_SelectionChangeCommitted(cboSize, e);
}
private void cboSize_SelectionChangeCommitted(object sender, EventArgs e)
{
string carSelected;
carSelected = Convert.ToString(cboSize.SelectedValue);
if (!gridInitialized)
{
dgvVehicles.DataSource = vehicleBindingSource;
gridInitialized = true;
ChangeGridColumns();
}
vehicleBindingSource.Filter = "CarSize = '" + carSelected + "'";
}
private void ChangeGridColumns()
{
//Change column headers
//dgvVehicles.Columns["Inv_ID"].Visible = false;
}
}
}
Try using SelectedIndexChanged event from the events menu after clicking on the combobox in the design view.
This should populate in your code:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
Console.WriteLine("test!");
}
In there you can put this logic from your code:
string carSelected;
carSelected = Convert.ToString(cboSize.SelectedValue);
if (!gridInitialized)
{
dgvVehicles.DataSource = vehicleBindingSource;
gridInitialized = true;
ChangeGridColumns();
}
vehicleBindingSource.Filter = "CarSize = '" + carSelected + "'";
Use SelectedIndexChanged instead of SelectionChangeCommitted.
I'm putting together a simple UI that interacts with a SQL database. My problem is a UI problem, ever time a menustrip item is selected, it opens a new active window. How do I set this up to close the previous active window? I've tried using Form.Close();, but that just closes everything.
private void addCampusToolStripMenuItem_Click(object sender, EventArgs e)
{
if_add_campus go = new if_add_campus();
go.Show();
}
private void addDepartmentToolStripMenuItem_Click(object sender, EventArgs e)
{
if_add_dept go = new if_add_dept();
go.Show();
}
private void addEmployeToolStripMenuItem_Click(object sender, EventArgs e)
{
if_add_employee go = new if_add_employee();
go.Show();
}
Just keep track of the last form you created in a variable:
private Form lastForm;
private void showForm(Form frm) {
frm.FormClosed += (sender, ea) => {
if (object.ReferenceEquals(lastForm, sender)) lastForm = null;
};
frm.Show();
if (lastForm != null) lastForm.Close();
lastForm = frm;
}
And use showForm() to display your forms:
private void addCampusToolStripMenuItem_Click(object sender, EventArgs e)
{
showForm(new if_add_campus());
}
Not tested, should be close.