Getting the deleted record from a bindingNavigator - c#

Using C# Winforms, I have a form with a BindingNavigator.
When the user clicks the delete button I want to log the record before it is deleted.
It is easy to tell that delete has been clicked using
private void bindingSource_ListChanged(object sender, ListChangedEventArgs e)
{
if (e.ListChangedType == ListChangedType.ItemDeleted)
{
}
}
However BindingSource.ListChanged is a completed event which fires after the row
deletion is done. When this event is firing, the row is already deleted so how can I trap it?
I am binding to a list of objects.
this.bindingSource.DataSource = Controller.Data; // returning a List<Person>()
this.bindingNavigator.BindingSource = this.bindingSource;
.

The bindingNavigator has a ToolStripItem called bindingNavigatorDeleteItem
The bindingNavigator's DeleteItem property had been set to this ToolStripItem.
Instead I set it to none.
Then set the Click Event of the bindingNavigatorDeleteItem ToolStripItem
this.bindingNavigatorDeleteItem.Click += this.bindingNavigatorDeleteItem_Click;
private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
{
this.bindingSource.EndEdit();
MyLogger( this.bindingSource.Current);
this.bindingSource.RemoveCurrent();
}

Related

How to Stop DataGridView editing after checked cell?

I use ContexMenuStrip on DataGridView to delete some rows but it doesn't work correctly.
Every time if I checked 3 rows, after selecting the ContexMenuStrip it only deletes 2 rows. When I do this code without the ContexMenuStrip (by Button) that works correctly.
When I see the behavior I understand current row is editing but doesn't finish. After double clicking on the current row to stop editing my ContexMenuStrip works correctly.
How to stop editing after checking the CheckBox?
When a cell has been selected and edited, the DataGridView property IsCurrentCellDirty is set to True. If you catch the event handler when this state changes on a DataGridViewCheckBoxCell, you can call DataGridView.EndEdit() to finalize those changes immediately.
this.dataGridView1.CurrentCellDirtyStateChanged += DataGridView1_CurrentCellDirtyStateChanged;
private void DataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (this.dataGridView1.IsCurrentCellDirty && this.dataGridView1.CurrentCell is DataGridViewCheckBoxCell)
{
this.dataGridView1.EndEdit();
}
}
Further explanation:
Behind the scenes, DataGridView.IsCurrentCellDirty is updated whenever you edit the current cell. The first line of code above allows you to attach to the CurrentCellDirtyStateChanged event your own event handler (DataGridView1_CurrentCellDirtyStateChanged) . So whenever the cell becomes dirty, behind the scenes will call the base level event and then your method as well. Without that line, your method will not be called. The += operator is what attaches your method to the event's call-chain.
For example, adding the following handlers:
this.dataGridView1.CurrentCellDirtyStateChanged += DataGridView1_Example1;
// this.dataGridView1.CurrentCellDirtyStateChanged += DataGridView1_Example2;
this.dataGridView1.CurrentCellDirtyStateChanged += DataGridView1_Example3;
private void DataGridView1_Example1(object sender, EventArgs e)
{
Console.WriteLine("Example 1");
}
private void DataGridView1_Example2(object sender, EventArgs e)
{
Console.WriteLine("Example 2");
}
private void DataGridView1_Example3(object sender, EventArgs e)
{
Console.WriteLine("Example 3");
}
When the dirty state changes, you'll see the following output. Notice the 2nd event handler was excluded:
// Example 1
// Example 3
There's a small problem in the code proposed by OhBeWise. It works for Mouse-Clicks. But if you toggle the checkbox with the Space key you can't toggle the checkbox again without manually switching the current cell first. With a small change it will work:
private void DataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (this.dataGridView1.IsCurrentCellDirty && this.dataGridView1.CurrentCell is DataGridViewCheckBoxCell)
{
this.dataGridView1.EndEdit();
DataGridViewCell currentCell = this.dataGridView1.CurrentCell;
this.dataGridView1.CurrentCell = null;
this.dataGridView1.CurrentCell = currentCell;
}
}

Manage CheckedListBox ItemCheck event to run after an item checked not before

I am using CheckedListBox in C# Window Forms Application.
I want to do something after one item checked or unchecked but ItemCheck event runs before the item checked/unchecked .
How can I do that?
CheckedListBox.ItemCheck Event
The check state is not updated until after the ItemCheck event occurs.
To run some codes after the item checked, you should use a workaround.
Best Option
You can use this option (Thanks to Hans Passant for this post):
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
this.BeginInvoke(new Action(() =>
{
//Do the after check tasks here
}));
}
Another option
If in middle of ItemCheck Event, you need to know state of item, you should use e.NewValue instead of using checkedListBox1.GetItemChecked(i)
If you need to pass a list of checked indices to a method do this:
Using the code:
var checkedIndices = this.checkedListBox1.CheckedIndices.Cast<int>().ToList();
if (e.NewValue == CheckState.Checked)
checkedIndices.Add(e.Index);
else
if(checkedIndices.Contains(e.Index))
checkedIndices.Remove(e.Index);
//now you can do what you need to checkedIndices
//Here if after check but you should use the local variable checkedIndices
//to find checked indices
Another Option
In middle of ItemCheck event, remove handler of ItemCheck, SetItemCheckState and then add handler egain.
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
var control = (CheckedListBox)sender;
// Remove handler
control.ItemCheck -= checkedListBox_ItemCheck;
control.SetItemCheckState(e.Index, e.NewValue);
// Add handler again
control.ItemCheck += checkedListBox_ItemCheck;
//Here is After Check, do additional stuff here
}
Try searching more for answers, cause here it is
private void clbOrg_ItemCheck(object sender, ItemCheckEventArgs e)
{
CheckedListBox clb = (CheckedListBox)sender;
// Switch off event handler
clb.ItemCheck -= clbOrg_ItemCheck;
clb.SetItemCheckState(e.Index, e.NewValue);
// Switch on event handler
clb.ItemCheck += clbOrg_ItemCheck;
// Now you can go further
CallExternalRoutine();
}
And the link:
Which CheckedListBox event triggers after a item is checked?
You can hook up an event on ItemCheck. You can do it by right clicking your checkboxlist and select properties. And at the right side you will see the property tab, click the event tab button and locate ItemCheck event and double click it. It will generate a event method for you depend on your checkboxlist name like below.
Then, you can verify selected/checked checkbox using code below.
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
var checkBoxName = checkedListBox1.Items[e.Index];
Console.WriteLine("Current {0}, New {1} , value {2}", e.CurrentValue, e.NewValue, checkBoxName);
}

How to get the column index of a DataGridView through click of ContextMenu in Winforms?

I have a DataGridView with 9 columns.
I have added the same ContextMenuStrip for all the column headers.
dataGridView.Columns[i].HeaderCell.ContextMenuStrip = myContextMenuStrip;
myContextMenuStrip contains a single item named Hide Column.
Now, I have an event handler for hidecolumnClick event and I want to find out which column header has been clicked inside the event handler?
Is there a way to do this?
Subscribe to the DataGridView.CellMouseDown event. In the event handler, store the column index or show the required context menu.
Sample Code:
void datagridview1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
//get the RowIndex or ColumnIndex from the event argument
}
}
Hi I have come up with another soution if u want to use the same object of ContextMenu for all the header. check it out..
Bind the CellMouseDown event on Grid-
dataGridView1.CellMouseDown += new DataGridViewCellMouseEventHandler(dataGridView1_CellMouseDown);
and in cellmousedown set the value of column clicked as below -
int columnClicked = -1;
void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
columnClicked = e.ColumnIndex;
}
now you can access the column clicked value in context menu item clicked event as below
private void helloToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show(columnClicked.ToString());
}
It is excepted u have assign the context menu to header already..
if you want i can give u the sample also..

Action immediately after selecting Item

I have this code:
private void button1_Click(object sender, EventArgs e)
{
if (comboBox1.SelectedItem.ToString() == "blahblah")
{
processing ps = new processing();
pictureBox1.Image = ps.blahblah(bmp);
}
else
{...
}
}
So the action of the ComboBox is done by clicking on the button1.
It is possible to take action immediately after selecting Item? without button clicking?
Subscribe to the SelectedIndexChanged event
comboBox1.SelectedIndexChanged += OnSelectedIndexChanged;
private void OnSelectedIndexChanged(object sender, EventArgs e) {
// Handle combo box changing
}
Try using this event,
ComboBox1.SelectedIndexChanged
and do
AutoPostBack = "true"
in your mark up if you want to check the selected item immediately after selecting item.

C# ComboBox GotFocus

I have a C# ComboBox using WPF. I have code that executes when the ComboBox's GotFocus is activated. The issue is that the GotFocus event is executed every time a selection is made from the ComboBox. For example, the GotFocus is executed when you first click on the ComboBox and then when you make a selection even though you have not click on any other control.
Is it possible to prevent this event from firing if a selection is being made in the list or is there a flag or something else in the event handler that can be used to determine if the GotFocus event handler was fired as a result of the user selecting an item in the list?
You can solve this problem with next verification:
private void myComboBox_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(ComboBoxItem))
return;
//Your code here
}
This code will filter all focus events from items (because they use bubble routing event). But there is another problem - specific behaviour of WPF ComboBox focus: when you open drop-down list with items your ComboBox losing focus and items get. When you select some item - item losing focus and ComboBox get back. Drop-down list is like another control. You can see this by simple code:
private void myComboBox_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem))
{
Trace.WriteLine("Got " + DateTime.Now);
}
}
private void myComboBox_LostFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem))
{
Trace.WriteLine("Lost " + DateTime.Now);
}
}
So you will get anyway atleast two focus events: when you select ComboBox and when you selecting something in it (focus will return to ComboBox).
To filter returned focus after selecting item, you can try to use DropDownOpened/DropDownClosed events with some field-flag.
So the final code with only 1 event of getting focus:
private bool returnedFocus = false;
private void myComboBox_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem) && !returnedFocus)
{
//Your code.
}
}
private void myComboBox_LostFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem))
{
ComboBox cb = (ComboBox)sender;
returnedFocus = cb.IsDropDownOpen;
}
}
Choose from this examples what you actually need more for your application.
I'm not too hot on WPF; but if you're trying to detect changes to the list (click on new value etc) you can use SelectedIndexChanged events..
On the other hand, if you really do want to know simply when the control is focussed, can you filter it by saying something like;
if (combo1.Focused && combo1.SelectedIndex == -1)
{
...
}
.. ? It really depends on what youre trying to detect, exactly.
Another solution is used is to determine whether the new focused element is an existing item in the combobox. If true then the LostFocus event should not be performed, because the combobox still has focus. Otherwise an element outside the combobox received focus.
In the code snipplet below I added the functionality in a custom combobox class
public class MyComboBox : System.Windows.Controls.Combobox
{
protected override void OnLostFocus(RoutedEventArgs e)
{
//Get the new focused element and in case this is not an existing item of the current combobox then perform a lost focus command.
//Otherwise the drop down items have been opened and is still focused on the current combobox
var focusedElement = FocusManager.GetFocusedElement(FocusManager.GetFocusScope(this));
if (!(focusedElement is ComboBoxItem && ItemsControl.ItemsControlFromItemContainer(focusedElement as ComboBoxItem) == this))
{
base.OnLostFocus(e);
/* Your code here... */
}
}
}

Categories