how to trigger a "panel update controls" when underlying dataset changes - c#

currently I have a datatable that is ordered by an 'enablelocation' field as a user can add items and reposition them. this datatable is then used to create user controls that are added to a panel.
Currently we are clearing the controls and then rebuilding the panel each time there is a change (whih isn't often, but it still happens) so I am looking for a way of updating the controls on the panel when there is a change.
the current code is this:
private void UpdateCats(int formid) {
//update dataset
cassess.Tables["CaseAssessDefCats"].Clear();
DataTable tcats = Requests.SQLGen.ProcessSQLCommand(gobj, null, "select id,name,shownohistory, case when EnableLocation is null then 1 else EnableLocation end as EnableLocation,FormID from CaseAssessDefCats where EnableLocation >= 0 and FormID = " + formid + " order by EnableLocation, Name", false, true);
if (tcats != null && tcats.Rows.Count > 0) {
tcats.TableName = "CaseAssessDefCats";
cassess.Merge(tcats);
}
//end update dataset
try {
if (_processing) { //check if update is running
return;
}
ClearAssessment(); //removes all the controls
_processing = true;
panMain.Refresh();
panMain.SuspendLayout();
//loop through datatable, re-adding them as controls
for (int a = cassess.CaseAssessDefCats.Rows.Count - 1; a >= 0; a--) {
trow = cassess.CaseAssessDefCats[a];
tcat = new CaseAssessDefCat(cassess, trow, gobj);
tcat.Tag = trow.ID;
tcat.catUp += new EventHandler(CatUp);
tcat.catDown += new EventHandler(CatDown);
tcat.catDelete += new EventHandler(CatDelete);
tcat.catEnter += new EventHandler(CatEnter);
tcat.catLeave += new EventHandler(CatLeave);
tcat.catEdit += new EventHandler(CatEdit);
tcat.catNew += new EventHandler(CatNew);
panMain.Controls.Add(tcat);
tcat.Dock = DockStyle.Top;
}
panMain.ResumeLayout();
_processing = false;
return;
} catch {
panMain.ResumeLayout();
_processing = false;
return;
}
}

Related

Multiselect list items overwrites instead of adding

I'm trying to add multi-selected items to list _AT.SOrderDetails = new List<SOrderDetail>(); but the list is overwritten by the last record selected. The list at right Datagrid only shows data of the last selected record of the left Datagrid instead of all records
foreach (int i in ((GridView)gridControl3.MainView).GetSelectedRows())
{
DataRowView oSOrder = (DataRowView)((GridView)gridControl3.MainView).GetRow(i);
int id = Convert.ToInt32(oSOrder.Row.ItemArray[0]);
if (oSOrder == null)
{
MessageBox.Show("select an item to edit", "Item not yet selected", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
int x = Convert.ToInt32(oSOrder["SOrderID"]);
_Order = db.SOrderTables.FirstOrDefault(o => o.QSOrdersID == x);
SOrderTable oOrder = null;
oOrder = _Order;
if (_Order != null)
{
_AT.SOrderDetails = new List<SOrderDetail>();
if (_Order.SOrderDetails != null)
{
foreach (SOrderDetail oPODItem in _Order.SOrderDetails.ToList())
{
_OrderDetail = new SOrderDetail();
Product oProduct = db.Products.FirstOrDefault(o => o.ProductID == oPODItem.ProductID);
_OrderDetail.ProductID = oPODItem.ProductID;
_OrderDetail.Description = oProduct.Description;
_OrderDetail.Quantity = oPODItem.Quantity;
_OrderDetail.Form = oPODItem.Form;
_OrderDetail.Price = oPODItem.Price;
_AT.SOrderDetails.Add(_OrderDetail);
}
}
}
}
The list at right Datagrid only shows data of the last selected record of the left datagrid
How do I add all values of the selected records, I need help I'm still new, thank you.
i created a new list _tapiwa.SOrderDetails = new List<SOrderDetail>(); So i was now saving information from list _Order.SOrderDetails.ToList(); to the new list i created.
`foreach (int i in ((GridView)gridControl3.MainView).GetSelectedRows())
{
DataRowView oSOrder = (DataRowView)((GridView)gridControl3.MainView).GetRow(i);
int id = Convert.ToInt32(oSOrder.Row.ItemArray[0]);
if (oSOrder == null)
{
MessageBox.Show("select an item to edit", "Item not yet selected", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
int x = Convert.ToInt32(oSOrder["SOrderID"]);
_Order = db.SOrderTables.FirstOrDefault(o => o.QSOrdersID == x);
label1.Text += (oSOrder.Row.ItemArray[0]).ToString()+" "+ (oSOrder.Row.ItemArray[1]).ToString()+" " + (oSOrder.Row.ItemArray[2]).ToString()+ "\n";
SOrderTable oOrder = null;
// db = new MedriveEntities();
oOrder = _Order;
if (_Order != null)
{
if (_tapiwa == null)
{
_tapiwa = new SOrderTable();
_tapiwa.SOrderDetails = new List<SOrderDetail>();
}
foreach (SOrderDetail oPODItem in oOrder.SOrderDetails.ToList())
{
_OrderDetail = new SOrderDetail();
// label2.Text += oPODItem.ProductID.ToString() + " " + oPODItem.Description.ToString() + " " + oPODItem.Quantity.ToString() + "\n";
Product oProduct = db.Products.FirstOrDefault(o => o.ProductID == oPODItem.ProductID);
_OrderDetail.ProductID = oPODItem.ProductID;
_OrderDetail.Description = oProduct.Description;
_OrderDetail.Quantity = oPODItem.Quantity;
_OrderDetail.Form = oPODItem.Form;
_OrderDetail.Price = oPODItem.Price;
_tapiwa.SOrderDetails.Add(_OrderDetail);
}
}
}
RefreshList1();`

Remove selected item in combobox

I want to remove a selected item in my combobox
I have here a code upon form load, I am filling list items on combobox from database.
private void LoadComboField()
{
//string test = "<ROOT><DATA FieldGroup=\"PAYMENT_VIEW4\" FieldDescription=\"PNAME\" Output=\"1\" Filter=\"1\" FieldName=\"PATIENTNAME\" DataType=\"STRING\"/><DATA FieldGroup=\"PAYMENT_VIEW4\" FieldDescription=\"MEMID\" Output=\"1\" Filter=\"1\" FieldName=\"MEMBERID\" DataType=\"STRING\"/></ROOT>";
ReadXMLData(XMLDOC, dsCombo);
// ReadXMLData(test, dsCombo);
dt = dsCombo.Tables[0];
DataView dv1 = new DataView(dsCombo.Tables[0]);
this.cmbField.Items.Clear();
this.cmbField.DataSource = dv1;
this.cmbField.DisplayMember = "FieldDescription";
this.cmbField.ValueMember = "FieldName";
}
Then I have this code on SelectedValueChanged
private void cmbField_SelectedValueChanged(object sender, EventArgs e)
{
DataGridViewRow GridRowLoc = this.dgvFilter.CurrentRow;
AddGrid(iRowIdx);
int iRowCount = this.dgvFilter.RowCount - 1;
//this.dgvFilter.CurrentRow.IsNewRow
//if (GridRowLoc.IsNewRow) continue;
// MessageBox.Show(this.dgvFilter.RowCount.ToString());
if (this.cmbField.Text != "System.Data.DataRowView")
{
this.dgvFilter.Rows[iRowIdx].Cells["ColumnFieldName"].Value = this.cmbField.Text;
this.dgvFilter.Rows[iRowIdx].Cells["FieldName"].Value = this.cmbField.SelectedValue;
if (iRowCount <= iRowIdx)
{
DataRow drow = dttable.NewRow();
drow["ColumnNames"] = this.cmbField.Text;
drow["FieldName"]= this.cmbField.SelectedValue;
drow["Alias"]=string.Empty;
drow["DataType"]=string.Empty;
drow["Outputs"]=false;
drow["SortType"]=string.Empty;
drow["SortOrder"]=string.Empty;
drow["GroupBy"]=string.Empty;
drow["Filter"]=string.Empty;
drow["Or1"]=string.Empty;
drow["Or2"]=string.Empty;
drow["Or3"]=string.Empty;
drow["Or4"]=string.Empty;
drow["Or5"]=string.Empty;
drow["Or6"]=string.Empty;
drow["Or7"]=string.Empty;
drow["Or8"]=string.Empty;
drow["Or9"]=string.Empty;
drow["Or10"]=string.Empty;
dttable.Rows.Add(drow);
}
else
{
int irow = 0;
foreach (DataRow dr in dttable.Rows)
{
if (irow == iRowIdx)
{
dr["ColumnNames"] = this.cmbField.Text;
dr["FieldName"] = this.cmbField.SelectedValue;
}
irow++;
}
}
CheckAlias(iRowIdx, this.cmbField.Text, dgvFilter);
checkcellvalue(this.cmbField.Text, iRowIdx);
CheckSorting();
if (bGroupBySelected == true)
{
this.dgvFilter.Rows[iRowIdx].Cells["GroupBy"].Value = "Group By";
}
this.dgvFilter.DataSource = dttable;
dsFilter.AcceptChanges();
this.cmbField.Visible = false;
}
// checkcellvalue(this.cmbField.Text, iRowIdx);
//MessageBox.Show(arr_Filter[0]);
CheckoutputEnable();
}
I have this code in SelectedIndexChanged
try
{
DataTable dt1 = new DataTable();
DataRowView oDataRowView = cmbField.SelectedItem as DataRowView;
string sValue = string.Empty;
if (oDataRowView != null)
{
sValue = oDataRowView.Row["FieldDescription"] as string;
}
//int count = dttable.Rows.Count - 1;
ComboBox comboBox = (ComboBox)sender;
// Save the selected employee's name, because we will remove
// the employee's name from the list.
string selectedEmployee = (string)sValue;
int count = 0;
int resultIndex = -1;
// Call the FindStringExact method to find the first
// occurrence in the list.
resultIndex = cmbField.FindStringExact(selectedEmployee);
// Remove the name as it is found, and increment the found count.
// Then call the FindStringExact method again, passing in the
// index of the current found item so the search starts there
// instead of at the beginning of the list.
while (resultIndex != -1)
{
cmbField.Items.RemoveAt(resultIndex);
count += 1;
resultIndex = cmbField.FindStringExact(selectedEmployee,
resultIndex);
}
// Update the text in Textbox1.
txtName.Text = txtName.Text + "\r\n" + selectedEmployee + ": "
+ count;
}
//}
catch (Exception ex)
{
}
But it throws an exception, say that "items collection cannot be modified when the datasource property is set." I don't know how to fix this exception error, I think that's my only problem when removing an item on the combobox.
Please do help me on this one. Thanks in advance!
Use a BindingSource for your DataSource and CurrentItemChanged to react of changed items in CBO:
this.source = new BindingSource();
this.source.DataSource = loDs.Tables[0];
this.cmbField.DataSource = this.source;
this.source.CurrentItemChanged += source_CurrentItemChanged;
Example for eventHandler:
private void source_CurrentItemChanged(object sender, EventArgs e)
{
System.Data.DataRowView view = this.source.Current as System.Data.DataRowView;
if (view != null)
{
System.Diagnostics.Debug.WriteLine(view[0].ToString());
}
}
You can remove an item from the source like this:
this.source.RemoveAt(this.source.Find("FieldName", "PATIENTNAME"));
Show Details: A Detailed Data Binding Tutorial
You can't modify the Items collection when it comes from / is bound to a DataSource. Instead you need to modify the DataSource itself.
To delete the SelectedItem from the DataSource you can try this:
DataRowView item = cmbField.SelectedItem as DataRowView;
if (item != null) item.Delete();

Error adding usercontrol to windows form c#

I create a FaceDetectionEvent which is a user control and try to add it in windows form (still in the same project). But it keeps showing this error:
This is the FaceDetectionEvent code:
public partial class FaceDetectionEvent : UserControl
{
private System.Timers.Timer tListener;
private MySQL_DataAccess da = new MySQL_DataAccess();
private int iCurrentStatusIndex_ = 0;
private List<DataRow> lstFaceDetectionEvent = new List<DataRow>(20);
private ImageList cropImageList = new ImageList();
public FaceDetectionEvent()
{
InitializeComponent();
CreateColumns();
GetLastTwentyEvent();
tListener = new System.Timers.Timer(1000);
tListener.Elapsed += new System.Timers.ElapsedEventHandler(tListener_Elapsed);
tListener.Start();
}
public void GetLastTwentyEvent()
{
string strSQL = string.Format("SELECT * FROM av_status_log AS A LEFT JOIN avmediaserver AS B ON A.device_id=B.DeviceId "
+ "LEFT JOIN privilege_device AS C ON A.device_id = C.device_id "
+ "LEFT JOIN privilege_device_group AS D ON C.device_group_id = D.device_group_id "
+ "WHERE event_type_id = 8 ORDER BY A.db_time DESC LIMIT 20");
DataTable dt = da.GetInfoData(strSQL).Tables[0];
if (dt.Rows.Count > 0)
iCurrentStatusIndex_ = Convert.ToInt32(dt.Rows[0]["rowid"]);
foreach (DataRow dr in dt.Rows)
{
lstFaceDetectionEvent.Add(dr);
string strCroppedImage = GetCropImageBase64String(dr["memo"].ToString());
cropImageList.Images.Add(Base64ToImage(strCroppedImage));
}
ShowFDEvent();
}
void tListener_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
string strSQL = string.Format("SELECT * FROM av_status_log AS A LEFT JOIN avmediaserver AS B ON A.device_id=B.DeviceId "
+ "LEFT JOIN privilege_device AS C ON A.device_id = C.device_id "
+ "LEFT JOIN privilege_device_group AS D ON C.device_group_id = D.device_group_id "
+ "WHERE A.rowid > {0} AND event_type_id = 8 ORDER BY A.db_time DESC", iCurrentStatusIndex_.ToString());
DataTable dt = da.GetInfoData(strSQL).Tables[0];
if (dt.Rows.Count > 0)
iCurrentStatusIndex_ = Convert.ToInt32(dt.Rows[0]["rowid"]);
if (lstFaceDetectionEvent.Count >= 20)
{
lstFaceDetectionEvent.RemoveRange(0, dt.Rows.Count);
for (int i = 0; i < dt.Rows.Count; i++)
{
cropImageList.Images.RemoveAt(i);
}
}
foreach (DataRow dr in dt.Rows)
{
lstFaceDetectionEvent.Add(dr);
string strCroppedImage = GetCropImageBase64String(dr["memo"].ToString());
cropImageList.Images.Add(Base64ToImage(strCroppedImage));
}
ShowFDEvent();
this.Refresh();
}
public string GetCropImageBase64String(string pStrMemo)
{
XElement doc = XElement.Parse(pStrMemo);
string strCropImage = doc.Element("cropImage").Value;
return strCropImage;
}
public Image Base64ToImage(string base64String)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(base64String);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
// Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length);
Image image = Image.FromStream(ms, true);
return image;
}
private void CreateColumns()
{
ColumnHeader cropImageHeader = new ColumnHeader();
cropImageHeader.Text = "Crop Image";
cropImageHeader.Width = 150;
FDEventlistView.Columns.Add(cropImageHeader);
ColumnHeader timestampHeader = new ColumnHeader("Event Time");
timestampHeader.Text = "Event Time";
timestampHeader.Width = 150;
FDEventlistView.Columns.Add(timestampHeader);
ColumnHeader deviceNameHeader = new ColumnHeader("Device Name");
deviceNameHeader.Text = "Size";
deviceNameHeader.Width = 80;
FDEventlistView.Columns.Add(deviceNameHeader);
}
private void ShowFDEvent()
{
FDEventlistView.Items.Clear();
FDEventlistView.BeginUpdate();
int i = 0;
foreach (DataRow dr in lstFaceDetectionEvent)
{
ListViewItem item = new ListViewItem();
item.ImageIndex = i;
ListViewItem.ListViewSubItem subitem = new ListViewItem.ListViewSubItem();
subitem.Text = dr["status_time"].ToString();
item.SubItems.Add(subitem);
subitem = new ListViewItem.ListViewSubItem();
subitem.Text = dr["device_name"].ToString();
item.SubItems.Add(subitem);
FDEventlistView.Items.Add(item);
i++;
}
FDEventlistView.EndUpdate();
}
}
Do you have any idea why?
Code in your UserControl will run at design time as well. A feature that provides the WYSIWIG behavior of a control when you drop it on a form with the designer. But certainly can be troublesome, in this case you do not want to query the dbase, no chance that you'll be able to find the correct connection string when the control is loaded in Visual Studio instead of your program. Simply skipped by using the DesignMode property:
public FaceDetectionEvent()
{
InitializeComponent();
tListener = new System.Timers.Timer(1000);
tListener.Elapsed += new System.Timers.ElapsedEventHandler(tListener_Elapsed);
if (!this.DesignMode) {
CreateColumns();
GetLastTwentyEvent();
tListener.Start();
}
}
You may need to insert the DesignMode test in other places in your code, like Paint and Load event handlers.
Do note how debugging such design-time only exceptions can be difficult, the message box isn't big enough to show you the stack trace. In the really hard cases you may need to debug Visual Studio itself so you can see the exception. Start another instance of VS and use Tools + Attach to Process to attach the debugger to the 1st instance. Debug + Exceptions, tick the Thrown checkbox to automatically break when the exception is thrown.
I don't think the problem is about UserControl. To prove this, create a new user control, this time not programmatically -> Add New and choose UserControl. Delete the FaceDetectionEvent Control from the MainForm for now, then add the newly created UserControl and see if the error shows up again. If it does please share the content of the StackTrace.
I've had this same issue trying to add my user controls to a form by dragging it from the tool box. It may seem obvious, but my issues involved having parameters in the constructor that were intended to be passed at run-time if the control was added programatically...
So this code will cause the error. To avoid it don't have arguments in the constructor.
public ucMyControl(string title)
{
InitializeComponent();
groupBox1.Text = title;
}

Combobox does not revert to null when value is cleared

Due to a flaw in .NET (Microsoft says its intended but I see it as a serious flaw)
If a user empties a combo box (i.e. wants to blank out the value) the selected value does not revert to null instead it keeps the last valid selected value, so when you save with a blank combobox it goes back to the original value.One workaround is to first choose a different option from the drop down, then blank it out and it will work properly. However, that's not something users of an application would prefer.
So is there a way that I can fix this. Or is it possible that I can add an option for "NONE" which will then change the value in the database to NULL. Note: Combobox has data-binding and I was not able to add the option none for Names.
Contents of the Form.Desginer.cs:
private void InitializeComponent()
{
......
this.cmbSecCSR = new System.Windows.Forms.ComboBox();
this.csrBindingSource2 = new System.Windows.Forms.BindingSource(this.components);
.....
//
// pnlCSRs
//
this.pnlCSRs.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pnlCSRs.Controls.Add(this.cmbSecCSR);
......
//
// cmbSecCSR
//
this.cmbSecCSR.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
this.cmbSecCSR.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
this.cmbSecCSR.DataSource = this.csrBindingSource2;
this.cmbSecCSR.DisplayMember = "Name";
this.cmbSecCSR.FormattingEnabled = true;
this.cmbSecCSR.Location = new System.Drawing.Point(112, 26);
this.cmbSecCSR.Margin = new System.Windows.Forms.Padding(0);
this.cmbSecCSR.Name = "cmbSecCSR";
this.cmbSecCSR.Size = new System.Drawing.Size(184, 21);
this.cmbSecCSR.TabIndex = 2;
this.cmbSecCSR.ValueMember = "Username";
this.cmbSecCSR.TextChanged += new System.EventHandler(this.comboBox_TextChanged);
this.cmbSecCSR.Enter += new System.EventHandler(this.cmbBox_Entered);
//
// csrBindingSource2
//
this.csrBindingSource2.DataMember = "CSR";
this.csrBindingSource2.DataSource = this.productionDS;
//..............
}
Above are the bits and pieces related to this combobox (I'm just fixing bugs in the application, and a newbie in C#.
The contents related to this combobox in the .CS file are the following:
private void loadDetails()
{
this.productionCrewTableAdapter.FillByProductionID(this.productionDS.ProductionCrew, productionID);
cmbSecCSR.DataBindings.Add("SelectedValue", productionMasterBindingSource, "CSR2", true, DataSourceUpdateMode.OnPropertyChanged);
}
private void comboBox_TextChanged(object sender, EventArgs e)
{
ComboBox cmbx = (ComboBox)sender;
if (cmbx.Equals(cmbCamSupplier))
{
}
else if (cmbx.Equals(cmbLGSupplier))
{
}
if (cmbx.Text.Length > 0) return;
cmbx.ResetText();
cmbx.SelectedIndex = -1;
}
private void cmbBox_Entered(object sender, EventArgs e)
{
ComboBox cmb = (ComboBox)sender;
String txt = cmb.Text;
if (cmb.Name.Contains("CSR"))
{
if (cmb != null)
{
((BindingSource)cmb.DataSource).Filter = (cmbOffice.SelectedIndex > -1 ? "Office = '" + cmbOffice.SelectedValue + "' AND " : "") + "IsCSR=1 AND Status=1";
cmb.Text = txt;
}
}
else if (cmb.Name.Contains("RC"))
{
int department = 0;
if (cmb != null)
{
if (cmb.Name.Contains("Camera"))
department = 2;
else if (cmb.Name.Contains("LG"))
department = 3;
else if (cmb.Name.Contains("Power"))
department = 4;
((BindingSource)cmb.DataSource).Filter = (cmbOffice.SelectedIndex > -1 ? "Office = '" + cmbOffice.SelectedValue + "' AND " : "") + "IsCSR=0 AND Status=1 AND (Department = " + department + " OR Department is null OR Department = 0)";
cmb.Text = txt;
}
}
}
If anyone can help me with this issue that I have been struggling with for a while, I'd really really appreciate it.
At the same time to your call clearing values with
this.cmbSecCSR.Items.Clear()
You have to do a
this.cmbSecCSR.Text = ""
or
this.cmbSecCSR.Text = "Default Text"
To clear the selected text in the combobox.

Datagrid View Button repeat

I have added button to datagrid view but when ever the function is called more than once then new button adds I need to stop this addition
void AddtoGrid()
{
try
{
table = new DataTable();
bcol = new DataGridViewButtonColumn();
bcol.HeaderText = "Action ";
bcol.Text = "Delete";
bcol.Name = "deleteUserButton";
bcol.UseColumnTextForButtonValue = true;
table.Columns.Add("Name");
table.Columns.Add("Type");
table.Columns.Add("Status");
table.Columns.Add("Date Created");
table.Columns.Add("Action");
for (int i = 0; i < userAction.UserName.ToArray().Length; i++)
{
row = table.NewRow();
asc.Add(userAction.UserName[i]);
row["Name"] = userAction.UserName[i];
row["Type"] = userAction.UserType[i];
row["Status"] = userAction.UserStatus[i];
row["Date Created"] = userAction.DateCrea[i];
row["Action"] = bcol.Text;
table.Rows.Add(row);
}
UsersView.DataSource = table;
UsersView.AllowUserToAddRows = false;//To remove extra row at the end
UsersView.Columns.Add(bcol);
}
catch (Exception ca)
{
MessageBox.Show(ca.ToString());
}
}//End Function for Getting Present Users
I'm not quite sure I understand your question, though I believe that you need to encapsulate creation of the new column into it's own method and only call it once - in the constructor for instance.
For example:
void CreateDeleteColumn()
{
bcol = new DataGridViewButtonColumn();
bcol.HeaderText = "Action ";
bcol.Text = "Delete";
bcol.Name = "deleteUserButton";
bcol.UseColumnTextForButtonValue = true;
UsersView.Columns.Add(bcol);
}
That should stop it adding a column every time you populate the list view.
Hope this helps and sorry if I misunderstood.
Tony

Categories

Resources