c# event fires windows form incorrectly - c#

I'm trying to understand what's happening here. I have a CheckedListBox which contains some ticked and some un-ticked items. I'm trying to find a way of determining the delta in the selection of controls. I've tried some cumbersome like this - but only works part of the time, I'm sure there's a more elegant solution. A maybe related problem is the myCheckBox_ItemCheck event fires on form load - before I have a chance to perform an ItemCheck. Here's what I have so far:
void clbProgs_ItemCheck(object sender, ItemCheckEventArgs e)
{
// i know its awful
System.Windows.Forms.CheckedListBox cb = (System.Windows.Forms.CheckedListBox)sender;
string sCurrent = e.CurrentValue.ToString();
int sIndex = e.Index;
AbstractLink lk = (AbstractLink)cb.Items[sIndex];
List<ILink> _links = clbProgs.DataSource as List<ILink>;
foreach (AbstractLink lkCurrent in _links)
{
if (!lkCurrent.IsActive)
{
if (!_groupValues.ContainsKey(lkCurrent.Linkid))
{
_groupValues.Add(lkCurrent.Linkid, lkCurrent);
}
}
}
if (_groupValues.ContainsKey(lk.Linkid))
{
AbstractLink lkDirty = (AbstractLink)lk.Clone();
CheckState newValue = (CheckState)e.NewValue;
if (newValue == CheckState.Checked)
{
lkDirty.IsActive = true;
}
else if (newValue == CheckState.Unchecked)
{
lkDirty.IsActive = false;
}
if (_dirtyGroups.ContainsKey(lk.Linkid))
{
_dirtyGroups[lk.Linkid] = lkDirty;
}
else
{
CheckState oldValue = (CheckState)e.NewValue;
if (oldValue == CheckState.Checked)
{
lkDirty.IsActive = true;
}
else if (oldValue == CheckState.Unchecked)
{
lkDirty.IsActive = false;
}
_dirtyGroups.Add(lk.Linkid, lk);
}
}
else
{
if (!lk.IsActive)
{
_dirtyGroups.Add(lk.Linkid, lk);
}
else
{
_groupValues.Add(lk.Linkid, lk);
}
}
}
Then onclick of a save button - I check whats changed before sending to database:
private void btSave_Click(object sender, EventArgs e)
{
List<AbstractLink> originalList = new List<AbstractLink>(_groupValues.Values);
List<AbstractLink> changedList = new List<AbstractLink>(_dirtyGroups.Values);
IEnumerable<AbstractLink> dupes = originalList.ToArray<AbstractLink>().Intersect(changedList.ToArray<AbstractLink>());
foreach (ILink t in dupes)
{
MessageBox.Show("Changed");
}
if (dupes.Count() == 0)
{
MessageBox.Show("No Change");
}
}
For further info. The definition of type AbstractLink uses:
public bool Equals(ILink other)
{
if (Object.ReferenceEquals(other, null)) return false;
if (Object.ReferenceEquals(this, other)) return true;
return IsActive.Equals(other.IsActive) && Linkid.Equals(other.Linkid);
}

There's little point that I see to do this in the ItemCheck event. Just calculate the delta when you save. Cuts out a bunch of code and trouble with spurious events.

Related

Some rows remains in a DataGrid when deleting multiple rows

I have a WPF triggered (TextChanged) function which calls two other function whose subroutine deletes rows from a DataGrid object when certain conditions are met.
I have a feeling I might be encountering race conditions on the delete of multiple rows. When I place a MessageBox.Show("somethings'); in between the two functions, 2 rows from DataGrid are deleted as expected with the message box popping up in between delete actions.
deleteFunction("item1");
MessageBox.Show("something");
deleteFunction("item2");
However if I remove the MessageBox only the first function deletes a single row (item1)from DataGrid.
deleteFunction("item1");
deleteFunction("item2");
I have tried all sorts of ways to resolve this, Thread.Sleep(500) in between function calls, setting up a Queue to FIFO the requests, thread locking. async ... Nothing seems to work for me.
I'm not even sure it is actually a race condition issue anymore. I am starting to wonder if there is some Thread connection to the DataGrid object that the MessageBox is severing when invoked and releasing the control for another function to interact with.
Code below:
private void streamCode_TextChanged(object sender, TextChangedEventArgs e)
{
if (configurationSectionLoaded == true)
{
streamCodeAlphanumeric(streamCode.Text);
streamCodeIsChar128(streamCode.Text);
}
formEdited = true;
}
private bool streamCodeAlphanumeric(string value)
{
dataValidation dv = new dataValidation();
if (dv.isAlphanumeric(value))
{
streamCode.Background = Brushes.LightGreen;
editStreamcode.Background = Brushes.LightGreen;
editStreamcode.IsEnabled = true;
//MessageBox.Show("scE01 Deleting");
//q.Enqueue(new UILogDeleteQueue() { qEntryType = "scE01" });
try
{
UILogRemoveRow("scE01");
}
catch(Exception e)
{
MessageBox.Show(e.ToString());
}
return true;
}
else
{
editStreamcode.IsEnabled = false;
streamCode.Background = Brushes.LightPink;
UILogAddRow("scE01", "Stream Code", "Non-Alphanumeric Characters Detected!");
return false;
}
}
private bool streamCodeIsChar128(string value)
{
dataValidation dva = new dataValidation();
if (dva.isChar128(value))
{
streamCode.Background = Brushes.LightGreen;
editStreamcode.Background = Brushes.LightGreen;
editStreamcode.IsEnabled = true;
//MessageBox.Show("scE02 Deleting");
try
{
UILogRemoveRow("scE02");
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
return true;
}
else
{
editStreamcode.IsEnabled = false;
streamCode.Background = Brushes.LightPink;
UILogAddRow("scE02", "Stream Code", "Invalid Length Detected!");
return false;
}
}
Finally here is the delete row code:
private void UILogRemoveRow(string entryCode)
{
int rowCount;
rowCount = UILog.Items.Count;
if (rowCount > 0)
{
for (int i = 0; i < rowCount; i++)
{
DataGridRow row = (DataGridRow)UILog.ItemContainerGenerator.ContainerFromIndex(i);
var selectedItem = UILog.ItemContainerGenerator.ContainerFromIndex(i);
if (row != null)
{
UILogObject theItem = (UILogObject)row.DataContext;
if (theItem.entryType == entryCode)
{
UILog.Items.RemoveAt(i);
}
}
}
}
}
Any assistance would be greatly appreciated.
UPDATE: included UILogAddRow function
private void UILogAddRow(string entryCode, string entryIdentifier, string entryDetail)
{
bool itemExists = false;
int rowCount;
rowCount = UILog.Items.Count;
if (rowCount > 0)
{
for (int i = 0; i < rowCount; i++)
{
DataGridRow row = (DataGridRow)UILog.ItemContainerGenerator.ContainerFromIndex(i);
if (row != null)
{
UILogObject theItem = (UILogObject)row.DataContext;
if (theItem.entryType == entryCode)
{
itemExists = true;
}
}
}
}
else
{
//MessageBox.Show(rowCount.ToString());
}
if (itemExists != true)
{
UILog.Items.Add(new UILogObject() { entryType = entryCode, identifier = entryIdentifier, detail = entryDetail });
}
UILog.Items.Refresh();
}
instead of working with low-level container elements (DataGridRow), cast items to your known type, and then search and remove
private void UILogRemoveRow(string entryCode)
{
var item = UILog.Items.OfType<UILogObject>()
.FirstOrDefault(x => x.entryType == entryCode);
if (item != null)
UILog.Items.Remove(item);
}

DataGridViewCheckBox CheckedChange Event

I added Checkboxcolumn near my columns.
i googling a lot but i cant find a good answer.
I Want to make Btn_Edit.Visiable=false; if checkbox checked count is up to 1.
after my researches i go to Use CellContentClick event but it isn't work fine.
My Code:
private void GrdVw_Reception_CellContentClick_1(object sender, DataGridViewCellEventArgs e)
{
if (GrdVw_Reception.CurrentCellAddress.X == 0)
{
int UpTpOne = 0;
bool flag = false;
for (int i = 0; i < GrdVw_Reception.Rows.Count; i++)
{
if (Convert.ToBoolean(GrdVw_Reception.Rows[i].Cells["checkColumn"].Value) == true)
{
UpTpOne = UpTpOne + 1;
if (UpTpOne == 1)
{
flag = true;
}
else
{
flag = false;
}
}
}
if (flag == true)
{
Btn_Edit.Visible = true;
}
else
{
Btn_Edit.Visible = false;
}
}
}
In this step when i run the program and click on checkboxes for first Btn_Edit dont go to true and for secound click Btn_Edit.Visiable go to true.
I want checkedchange event or an event that when i click on checkbox go to event codes in that moment.
(Sorry for bad English)
I proved it myself and had to do this to work:
private void GrdVw_Reception_CellClick(object sender, DataGridViewCellEventArgs e)
{
if(e.ColumnIndex == TheColumnIndexOfTheCheckBoxColumn){
bool currentValue = !(bool)GrdVw_Reception.Rows[e.RowIndex].Cells[0].Value;
GrdVw_Reception.Rows[e.RowIndex].Cells[0].Value = currentValue;
GrdVw_Reception.EndEdit();
MessageBox.Show("Value " + currentValue.ToString());
}
}
When the even click happens the value haven't change, so, i changed it myself and call EndEdit() method of the dataGridView. It works that way.
private void GrdVw_Reception_CellContentClick_1(object sender, DataGridViewCellEventArgs e)
{
if (GrdVw_Reception.CurrentCellAddress.X == 0)
{
if (Convert.ToBoolean(GrdVw_Reception.Rows[e.RowIndex].Cells[0].Value) == false)
{
GrdVw_Reception.Rows[e.RowIndex].Cells[0].Value = CheckState.Checked;
}
else
{
GrdVw_Reception.Rows[e.RowIndex].Cells[0].Value = CheckState.Unchecked;
}
int UpTpOne = 0;
bool flag = false;
for (int i = 0; i < GrdVw_Reception.Rows.Count; i++)
{
if (Convert.ToBoolean(GrdVw_Reception.Rows[i].Cells["checkColumn"].Value) == true)
{
UpTpOne++;
if (UpTpOne == 1)
{
flag = true;
}
else
{
flag = false;
}
}
}
if (UpTpOne == 0)
{
Btn_DelRecord.Visible = false;
}
else
{
Btn_DelRecord.Visible = true;
}
if (flag == true)
{
Btn_Edit.Visible = true;
}
else
{
Btn_Edit.Visible = false;
}
}
}
In this code i made value of checkbox to true by code and then counting number of checkboxescell that has been checked.
I wanted make visiable of Btn_Edit go to false if the checked boxes number is up to one and.....
You should make checkbox tick to ticked and value of cell to true by code because when you click on gridviewcellcheckbox for first, the row go to selecting and in secound click the value going to be true.
I googled a lot but can't reach any good answer and this code is a total of my thinking if you have any good idea for do it better please call me.

How to disable more than one NumericUpDown controls using one method?

i have a form with more than one NumericUpDown as controls to input answer. i want every input is true for an operation (multiplication, sum etc), NumericUpDown for that operation will be disable. i have used the code below (just for sum operation), but i think its not efficient because i have to make a method to check every operation.
private void IsSumTrue() {
if (add1 + add2 == sum.Value)
{
sum.Enabled = false;
}
}
private void IsDifferenceTrue()
{
if (add1 - add2 == difference.Value)
{
difference.Enabled = false;
}
}
private void IsProductTrue()
{
if (add1 * add2 == product.Value)
{
product.Enabled = false;
}
}
private void IsQuotientTrue()
{
if (add1 / add2 == quotient.Value)
{
quotient.Enabled = false;
}
}
anyone have idea how to make it more efficient with just a method for all operation?
below is my idea, but to check the value is true for every NumericUpDown i don't know how.
private void DisableIfValueIsTrue()
{
foreach(Control control in this.Controls)
{
NumericUpDown value = control as NumericUpDown;
// if(value [NEED HELP]
}
}
Considering your situtaion, you can set a tag for each NumericUpDown in design mode like this:
sum.Tag=1;
square.Tag=2;
etc
Then define some int variables:
int iSum=add1+add2;
int iSquare= //Whatever you want
etc
And finally loop through your controls this way:
foreach (NumericUpDown control in this.Controls.OfType<NumericUpDown>())
{
int intCondition = Convert.ToInt32(control.Tag) == 1
? iSum
: Convert.ToInt32(control.Tag) == 2
? iSquare
: Convert.ToInt32(control.Tag) == 3
? i3
: i4; //You should extend this for your 8 controls
control.Enabled = intCondition == control.Value;
}
OK! Second way I offer
Since you will have to always check 8 different conditions, you could simply forget about looping through the controls and just change your method like this:
private void DisableIfValueIsTrue()
{
sum.Enabled = add1 + add2 != sum.Value;
difference.Enabled= add1 - add2 != difference.Value;
product.Enabled= add1 * add2 != product.Value;
quotient.Enabled= (add2 !=0) && (add1 / add2 != quotient.Value);
//etc
}
I came across this while doing some research and would like to give my solution I used for my situation and hope it helps people. I needed minimum and maximum numbers for a calculation, so mine are named appropriately and I correlated these with some CheckBoxes. I used null in beginning of minimum and end of maximum to account for empty. I also had to create an event handler SubscribeToEvents() shown below.
In my load event for my form:
SubscribeToEvents();
_checkBoxs = new[] { cbXLight, cbLight, cbMedium, cbHeavy, cbXHeavy, cbXXHeavy, cbXXXHeavy };
_minimumsNumericUpDowns = new[] { null, nLightMin, nMediumMin, nHeavyMin, nXHeavyMin, nXXHeavyMin, nXXXHeavyMin };
_maximumsNumericUpDowns = new[] { nXLightMax, nLightMax, nMediumMax, nHeavyMax, nXHeavyMax, nXXHeavyMax, null };
then I created a method:
private void DisableNumericUpDowns()
{
// disable everything:
foreach (var n in _minimumsNumericUpDowns)
{
if (n != null)
n.Enabled = false;
}
foreach (var n in _maximumsNumericUpDowns)
{
if (n != null)
n.Enabled = false;
}
}
The event handler:
private bool _eventsSubscribed;
private void SubscribeToEvents()
{
if (_eventsSubscribed)
return;
_eventsSubscribed = true;
cbXXHeavy.CheckedChanged += CheckBox_NumericState;
cbXHeavy.CheckedChanged += CheckBox_NumericState;
cbXLight.CheckedChanged += CheckBox_NumericState;
cbHeavy.CheckedChanged += CheckBox_NumericState;
cbLight.CheckedChanged += CheckBox_NumericState;
cbMedium.CheckedChanged += CheckBox_NumericState;
cbXXXHeavy.CheckedChanged += CheckBox_NumericState;
}
Now I can used this to check when they are enabled and if they are greater than or less than 0 if needed in the method CheckBox:
private void CheckBox_NumericState(object sender, EventArgs e)
{
// disable everything
DisableNumericUpDowns();
// see if more than one checkbox is checked:
var numChecked = _checkBoxs.Count((cb) => cb.Checked);
// enable things if more than one item is checked:
if (numChecked <= 1) return;
// find the smallest and enable its max:
var smallest = -1;
for (var i = 0; i < _checkBoxs.Length; i++)
{
if (!_checkBoxs[i].Checked) continue;
if (_maximumsNumericUpDowns[i] != null)
{
_maximumsNumericUpDowns[i].Enabled = true;
}
smallest = i;
break;
}
// find the largest and enable its min:
var largest = -1;
for (var i = _checkBoxs.Length - 1; i >= 0; i--)
{
if (!_checkBoxs[i].Checked) continue;
if (_minimumsNumericUpDowns[i] != null)
{
_minimumsNumericUpDowns[i].Enabled = true;
}
largest = i;
break;
}
// enable both for everything between smallest and largest:
var tempVar = largest - 1;
for (var i = (smallest + 1); i <= tempVar; i++)
{
if (!_checkBoxs[i].Checked) continue;
if (_minimumsNumericUpDowns[i] != null)
{
_minimumsNumericUpDowns[i].Enabled = true;
}
if (_maximumsNumericUpDowns[i] != null)
{
_maximumsNumericUpDowns[i].Enabled = true;
}
}
}
So I can check each state as required:
I want to check if Extra Light is check:
// Extra Light
if (!cbXLight.Checked) return;
if (nXLightMax.Enabled == false)
{
_structCategoryType = XLight;
CheckStructureSheets();
}
else
{
if (nXLightMax.Value > 0)
{
_dMax = nXLightMax.Value;
_structCategoryType = XLight;
CheckStructureSheets();
}
else
{
MessageBox.Show(#"Extra Light Max cannot be zero (0)");
}
}
and next light checks both:
// Light
if (cbLight.Checked)
{
if (nLightMin.Enabled == false && nLightMax.Enabled == false)
{
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
if (nLightMin.Enabled && nLightMin.Value > 0)
{
if (nXLightMax.Enabled && nLightMin.Enabled && nLightMax.Enabled == false)
{
_dMin = nLightMin.Value;
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
if (nLightMax.Value > 0)
{
_dMin = nLightMin.Value;
_dMax = nLightMax.Value;
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
MessageBox.Show(#"Light Max cannot be zero (0)");
return;
}
}
}
else if (nLightMin.Enabled == false && nLightMax.Enabled)
{
if (nLightMax.Value > 0)
{
_dMax = nLightMax.Value;
_structCategoryType = Light;
CheckStructureSheets();
}
else
{
MessageBox.Show(#"Light Max cannot be zero (0)");
}
}
else
{
MessageBox.Show(#"Light Min cannot be zero (0)");
return;
}
}
}
Hope this helps someone.
Tim
thanks for #AlexJoliq and #BrettCaswell. just want to inform that before Alex edited his answer from using "==" to "!=", i (thought) already solved the problem. but i don't know where is the more effective and efficient way, alex's or mine.
below is my code for DisableIfValueIsTrue():
if (add1 + add2 == sum.Value) sum.Enabled = false;
if (add1 - add2 == difference.Value) difference.Enabled = false;
if (add1 * add2 == product.Value) product.Enabled = false;
if (add1 / add2 == quotient.Value) quotient.Enabled = false;

background worker RunWorker Completed event is executed even before do work event

I have WPF application where in the Ui I have a header check box and when it is checked all the body checkboxes are checked. When any checkbox is checked, Im doing some work that I need by calling the Background worker which works perfect. If I select any checkboxes individually without checking header then Background worker works fine.
Problem is when I check the header all the body checkboxes are checked and in this case the Background worker 'Run Worker completed' event is being executed even before 'do work' is executed which is breaking my code. Please help. Here is my code. RunJob is from command for button in front end.
public void RunJob(object obj)
{
obforSave = obj;
workerforRun = new BackgroundWorker();
workerforRun.WorkerReportsProgress = true;
workerforRun.DoWork += workerforRun_DoWork;
workerforRun.ProgressChanged += workerforRun_ProgressChanged;
workerforRun.RunWorkerCompleted += workerforRun_RunWorkerCompleted;
if (!workerforRun.IsBusy)
{
workerforRun.RunWorkerAsync();
}
}
//Special case header is checked Runwroker completed is executing before do work.
void workerforRun_DoWork(object sender, DoWorkEventArgs e)
{
IsValidationsComplete = false;
int count = 0;
//var obj = e.Argument;
if (IsRunJobAlreadyExecuted == false)
{
ResultExtract = JobEntities.Any(s => s.ExtractIsSelected != null && (bool)s.ExtractIsSelected);
var resultTransform = JobEntities.Any(x => x.TransformIsSelected != null && (bool)x.TransformIsSelected);
var resultLoad = JobEntities.Any(b => b.LoadIsSelected != null && (bool)b.LoadIsSelected);
//Check if any of the entities are either Extracted, Transformed or Loaded.
if (ResultExtract || resultTransform || resultLoad)
{
SaveJobConfigurationChanges(obforSave);
var jobEngine = new JobEngine();
var jobId = JobEntities[0].JobId;
jobEngine.ProcessJob(jobId);
MessageBox.Show("Job Execution Complete", "Run Job");
AllResults = GetJobConfigurationResults();
foreach (var item in AllResults)
{
if (item.ExtractIsSelected == true && item.ExtractStatus == "Completed Successfully")
{
count += Convert.ToInt32(item.ExtractRowsSelected);
}
if (item.TransformIsSelected == true && item.TransformStatus == "Completed Successfully")
{
count += Convert.ToInt32(item.TransformRowsSelected);
}
if (item.LoadIsSelected == true && item.LoadStatus == "Completed Successfully")
{
count += Convert.ToInt32(item.LoadRowsSelected);
}
}
workerforRun.ReportProgress(count);
//MessageBox.Show(count.ToString());
}
else
{
//When No Entity is Selected and the Run Button is pressed.
MessageBox.Show("Select an Entity First");
}
}
IsRunJobAlreadyExecuted = false;
}
void workerforRun_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progress = e.ProgressPercentage;
}
void workerforRun_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
{
/*When Header is checked and when the Run is clicked, you want to Uncheck the header back after completion.
This property is set in the CS file.*/
AllResults = GetJobConfigurationResults();
foreach (var item in AllResults)
{
item.ExtractIsSelected = false;
item.TransformIsSelected = false;
item.LoadIsSelected = false;
}
SaveTaskSelection();
JobEntitiesCollectionViewSource.Source = AllResults;
JobEntitiesCollectionViewSource.View.Refresh();
ExecuteFilteredEntitiesStoredProcedure();
IsValidateEnabled = AllResults.Any(p => p.ExtractStatus == "Completed Successfully");
}), DispatcherPriority.Background, null);
MessageBox.Show(progress.ToString());
IsValidationsComplete = true;
}
CS file:
public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
// If there is a child found and if the child is of the T type.
//Dont remove null check . If no check i
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
private IEnumerable<CheckBox> GetAllCheckBoxs()
{
var allCheckBoxes = FindVisualChildren<CheckBox>(UserControlJob);
return allCheckBoxes;
}
private void ChkHeaderExtract_OnChecked(object sender, RoutedEventArgs e)
{
var extractCheckBoxes = GetAllCheckBoxs();
var i = 0;
foreach (var chk in extractCheckBoxes)
{
if (i%3 == 0) // Since I have many sets of checkboxes and I want only the first set of checkboxes checked when header is clicked Im doing this.
{
chk.IsChecked = true;
}
i++;
}
}

Check if flowLayoutPanel is empty in c#

I want to make an error label come up when my flowLayoutPanel is empty, but i don't know how to check that the flowLayoutPanel is empty. This is my current code:
private void flowLayoutPanel1_ControlRemoved(object sender, ControlEventArgs e)
{
if (flowLayoutPanel1.Controls == null)
{
customtoolwarning.Visible = true;
}
else
{
customtoolwarning.Visible = false;
}
}
Please Help,
Thanks
private void flowLayoutPanel1_ControlRemoved(object sender, ControlEventArgs e)
{
if (flowLayoutPanel1.Controls.Count > 0)
{
customtoolwarning.Visible = true;
}
else
{
customtoolwarning.Visible = false;
}
}
The problem you're running into is you're checking Controls for null to determine if it's empty. The Controls property won't ever be null but instead will be non-null and have 0 length when empty. For example
if (flowLayoutPanel1.Controls.Count == 0) {
// It's empty
}
lblNoContacts.Visible = (flowLayoutPanel.Controls.Count == 0) ? true : false;

Categories

Resources