Repository Combo BoxEdit EditValueChanged fires many times while typing. - c#

I have this Repository Item comboboxEdit in a Devexpress CustomGridView.
private void gridView1_CustomRowCellEditForEditing(object sender, DevExpress.XtraGrid.Views.Grid.CustomRowCellEditEventArgs e)
{
if (e.Column == this.gcCol1)
{
var repositoryItem = new RepositoryItemComboBox();
foreach (var title in this.ViewModelList.Titles)
{
repositoryItem.Items.Add(title.TitleName);
}
repositoryItem.EditValueChanged += this.PostEditValueChanged;
repositoryItem.Validating+=this.validating;
e.RepositoryItem = repositoryItem;
}
}
private void PostEditValueChanged(object sender, EventArgs e)
{
this.gridView1.PostEditor();
}
EditValueChanged fires many times while typing. Is there a way to fire this EditValueChanged once after the user has completely finished editing the cell.
Something along these lines http://www.devexpress.com/Support/Center/Question/Details/Q288616
Devexpress Support had some fix for this problem but didn't seem to help.
Not sure why the activeedior is closing and resetting the cursor.
I don't want to be setting the caret position in EditValueChanged.
I also tried CellvalueChanged but this would require a click in the usercontrol.
Same with repository.validating
repositoryItem.EditValueChanged += this.PostEditValueChanged;
repositoryItem.Validating+=this.validating;
Is there a way to figure out if the user is done or still editing the combox box and then fire the editvaluechanged without having to worrying out clicks outside the combo box edit

A better approach:
Handle the GridView's CellValueChanged event, rather than EditValueChanged on the editor.
In the handler, determine which column fired the event. For example,
if (e.Column.Equals(this.gvColTitle))
{
//Access the repository item:
ComboBoxEdit editor = this.gridView1.ActiveEditor as ComboBoxEdit;
//Assign your values to the editor.
}
I'm not sure why you're adding the repository item at runtime, but you may be able to just create it in the XtraGrid Designer screen, and assign it to the column there. You can still update its item list at runtime using the above.

I was able to resolve this issue by not firing the EditvalueChanged and using the Validating event.
This event fires when the editor is about to lose focus. Its unlike CellvalueChanged where if the user clicks on the form and not on the usercontrol, the change is lost.

gridView1.PostEditor(); will show the editor after populating the values. Similarly, We can change the validating event to fire on 'Enter Key' to resolve as a quick fix.

Related

WinForm C# DLL using ListBox - SelectedValueChanged Event firing inconsistently

I am developing a DLL which is loaded into a Tab page in a Enteprise application.
A ListBox control (single select) has an event on listBox_SelectedValueChanged where the use choosed between different "Display Styles" which when changes fires a sub-routine to reload a DataViewGrid control with different information. Code is below for this:
private void listBox_SelectedValueChanged(object sender, EventArgs e)
{
MessageBox.Show("LBSVC Value:" + listBoxDisplayStyles.SelectedValue + " -- Index:" + listBoxDisplayStyles.SelectedIndex);
if (listBoxDisplayStyles.SelectedValue != null)
PatientChanged(true); // true = force a refresh
}
Now inconsistently when finished interacting with DGV control (no editing, just scrolling and ToolTip triggering to show extended information on the cells) I move the mouse back over the listbox control and click a different line to. The new listbox line becomes current (selection bar appears), but the event does not seem to be triggered (ie the MessageBox does not appear and nothing happens.
Why don't you try SelectedIndexChanged event instead. Therein you can still use listBox.SelectedValue to fetch current value and act accordingly.
BTW it looks like you're working with more than one ListBox here. The event handler uses the object name listBox whereas the event body uses listBoxDisplayStyles. That might have something to do with the problem you're facing. But first try SelectedIndexChanged and let us know.

How can I know Text changes for textboxes without Textchanged event

In my C# Windows form MyForm I have some TextBoxes.
In these TextBoxes, we have to detect if the TextChanged event occurs,
if there're changes in these TextBoxes and click close button, it will ask if we want to cancel the changes when we close the form.
However, when I run the MyForm, I can't know text change for each textbox caused by user typing for without textchanged event property.
But I am thinking how do I make the TextBox's TextChanged know the
event cuased by user typing without textchanged event?
Thanks for help.
Sorry for my English.
There is no (decent) way of knowing what's typed without a TextChanged or a Leave event.
You need to use one of these events to get the typed content. Doing this enable you to set a "dirty" flag that you can check at close and clear at save.
Comparing old and new value has no point without this cause you won't know what the value should be set to without knowing something was changed.
With one exception: If your original data came from a database you could use the compare old/new approach as you would compare the textbox of that which came from the database.
Update:
Addressing this comment:
"Because Myform have many textboxes and if no text change ,this will
not display the confirm message.If I catch textchanged event for all
textboxes, this is so many code."
You can use a common handler to collect the changes for all textboxes in one single method. Use the sender object (cast it to Textbox) to identify which textbox is changed, if needed, or simply set a dirty flag for whatever textbox has a change.
bool isDirty = false;
void SomeInitMethod() //ie. Form_Load
{
textbox1.TextChanged += new EventHandler(DirtyTextChange);
textbox2.TextChanged += new EventHandler(DirtyTextChange);
textbox3.TextChanged += new EventHandler(DirtyTextChange);
//...etc
}
void DirtyTextChange(object sender, EventArgs e)
{
isDirty = true;
}
void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (isDirty) {
//ask user
}
}
// to clear
void Save()
{
SaveMyDataMethod();
isDirty = false;
}
If you have a lot of textboxes in the form loop through the forms control collection and use typeof to address the textboxes. If you have textboxes requiring different approaches use the Tag property of the textbox to distinguish.
A possible approach is using the timer. Have a timer that ticks every 1000 ms (say) and checks the textBox.Text.
A second possible approach is overriding WndProc for the textbox (by inheriting a new class) and handling the change text message. This would be the same as overriding TextBox.OnTextChanged.
Why dont you use a timer which will check after a few intervals if the textboxes do contain any text

Preventing user selection but allowing selection programmatically

I have a listview control in my windows application, which is populated with some set of items. I will make the selection of an item programmatically by setting ListViewItem.Selected property to true. But I want to prevent the user from selecting an item in the listview. i.e., it should be always selected programmatically. I can prevent the user selection by disabling the control, but disabling the control will also disable the scroll bars which is not correct.
Even I have created a custom listview control and implemented a ItemSelectionChanging eventhandler using WndProc check link, using which i can cancel the event as shown below,
private void lstLiveTables_ItemSelectionChanging(object sender, ListViewExItemSelectionChangingEventArgs e)
{
e.Cancel = true;
}
But again, this will cancel the event, even for an item selected programmatically. My question, is there anyway to identify whether the selection is made manually (by user) or programmatically in SelectedIndexChanged or using WndProc Message.
Note: If it is required, I will upload the code of CustomListView control.
Update 1
Thanks emartel. It was a good thought. Even I tried to achieve the same thing by subscribing to the event only before selecting the item and removed it immediately after selecting. By this way, upon selection the event will be immediately triggered and it will continue. This is working fine.
this.lstTables.SelectedIndexChanged += new System.EventHandler(this.lstTables_SelectedIndexChanged);
item.Selected = true;
this.lstTables.SelectedIndexChanged -= new System.EventHandler(this.lstTables_SelectedIndexChanged);
But again I have a problem that, if the user selects an item manually, nothing will happen (no event will be triggered) but the item alone will be highlighted. Once an item is highlighted and if i try to select the same item programmatically nothing is happening i.e., the SelectedIndexChanged event is not getting triggered for that item as it is already highlighted.
Note: Same behavior even if I follow the Flag approach suggested by you.
Update 2
I can solve this issue by having my own method instead of handling through events as emartel's suggestion. But my question is, according to my update 1, is there anyway to trigger the SelectedIndexChanged event when the item is highlighted but not actually selected?
public FrmTest()
{
list.ItemSelectionChanged += list_ItemSelectionChanged;
}
private bool changing;
private void list_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (changing)
return;
if (e.Item == nonSelectableListItem)
{
changing = true;
nonSelectableListItem.Selected = false;
changing = false;
}
}
Sample:
Well, an easy solution would be to keep a flag saying that you are programmatically changing the selection and to allow the event to pass, and reset the flag when you're done
Edit: if you, and only you, can change the selection, and you do this programmatically, so you have control over where and when this happens, why do you even need the EventHandler? Why not call a method to do whatever processing you want to happen?
One dirty way to do that is to keep list of selected items and refresh selection every time it changes other way than from your code.
There is also an ItemSelectionChanged event which is raised separately for every item whose selection state have changed. You can probably flip the selection state back it this event.
You may also take a look on Better ListView Express control. It have a read-only mode, so that user cannot change the selection. Its setup is very simple:
listView.ReadOnly = true;
The full version also supports custom non-selectable items. Simply setting:
listView.Items[0].Selectable = false;
make the first non-selectable (by the user).
You can still select items from code, of course.
The following image shows non-selectable items in action (they are marked by gray color):

How do you get the fact that a cell of a datagridview has been modified without the cell losing focus?

I have a datagridview with a check box in it. The point is when the user clicks the check box I immediately want to perform an action. The problem I have is, If I process the cell click method this does not work if the user uses the keyboard. I can tie onto the currentcelldirtystatechanged event but this is only raised the first time the cell is changed but not subsequent times. Essentially I want to act immediately and not force the user to change the cell that is currently in focus.
Use the CurrentCellDirtychanged event and the IsCurrentCellDirty property.
// This event handler manually raises the CellValueChanged event
// by calling the CommitEdit method.
void dataGridView1_CurrentCellDirtyStateChanged(object sender,
EventArgs e)
{
if (dataGridView1.IsCurrentCellDirty)
{
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
There is a "CellEnter" event that will be raised when a cell gains focus, however that may happen. The user may not have changed anything yet, but the behavior you describe (clicking on the cell or tabbing/arrowing into it) doesn't require them to.

How to detect cell click in DataGrid?

How to detect what specific cell was clicked in DataGrid?
I'm pretty sure you're looking for the selectedindexchanged event
Did you try to handle CellClik or CellContentClick events?
Suppose I haven't found this answer as well, (To determine a cell click).
And suppose I wanted to use it to be able to check/uncheck a checkbox, upon first click.
Then I guess the designer of this library would not approve of doing, it the following way, (I can (de)select my checkbox this way, but it seems unwise/dangerous as your changing the selected item property of the grid.)
So what we need is someone telling us how we can detect a cell's click otherwise some of us
may want to use the selectionchanged event, the bad thing about this is that you lose info on
which row of the grid pass pressed.
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (dataGridInstance.SelectedItem != null)
{
//do what you need to do with the data. (for example start with:)
Microsoft.Windows.Controls.DataGridCellInfo datagridCellInfo = dataGridInstance.CurrentCell;
//when you are done, set selectiTem to null, so even upon a next click on the same
//cell this method will be called again
dataGridTeam.SelectedItem = null;
}
}

Categories