WinForm C# DLL using ListBox - SelectedValueChanged Event firing inconsistently - c#

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.

Related

Repository Combo BoxEdit EditValueChanged fires many times while typing.

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.

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 to bypass the enter/leave event in c sharp

I'm having a Picture box in a user control window(Windows custom control library). and some functionality in the Form's Enter event and leave event.
Now my sample application is having two instances of the control. So when i run my sample application the fist control got selected and the enter event is triggered, and when i select the second control the first's leave and second's enter events are getting triggered.
Now, problem is that when i select(click) the second control's picturebox, the events are not triggering, i.e the control form is not getting the event.
So if i click whereever in the control(in the picturebox or in the control) the enter event should be triggered.
How to do this?
A picture box can't get focus. So clicking on it won't take the focus away from the previous control thus not triggering the events.
You need to add a click handler on the picture box in which you manually give focus to the associated focusable control.
private void PictureBox_Click(object sender, EventArgs e)
{
focusableControl.Focus();
}

WinForm - TabStop Not Working

I have a WinForm with 3 group boxes, one with combo boxes, and two with radio buttons. I set all of them and their children controls to "TabStop = false", but when I cycle with TAB, the currently selected radio button in each of the last two group boxes gets focused.
If there's no way to change this behavior, what would be a good event to catch and move the focus away? I can't find an "OnFocus" event.
The solution is to set one method (code below) to handle the "Enter" event of every radio button in the form (if that's what you wish).
Actually, I only did it for the radio buttons of the first group box and it worked, the second group box's radio buttons don't get focus, even though their "Enter" events are not handled. This is not the behavior you would have expected.
private void radiobuttonXGroup1_Enter(object sender, EventArgs e)
{
SomeOtherControl.Focus();
}
In the *.Designer.cs file you edit every Enter event (for each radio button) to point to one event handler (the above method).
this.radiobutton1Group1.Enter += new System.EventHandler(this.radiobuttonXGroup1_Enter);
this.radiobutton2Group1.Enter += new System.EventHandler(this.radiobuttonXGroup1_Enter);
this.radiobutton3Group1.Enter += new System.EventHandler(this.radiobuttonXGroup1_Enter);
Setting the TabStop to False on a RadioButton to prevent tabbing to the control works until you actully select the radio button without any additional overrides like suggested by #msergeant.
EDIT
The following code prevents the code from getting a tab key event:
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
radioButton1.TabStop = false;
}
Radio buttons behave differently with respect to Tab from other controls in that they work in sets or groups based on setting the tab index or placing then radio buttons in a group box.
The MSDN documentation for RadioButton.TabStop states "This API supports the .NET Framework infrastructure and is not intended to be used directly from your code". Which basically means, "This isn't going to work how you expect it to".
With that said, the Enter event will fire when the button receives the focus. You can try to use that to move focus to another control.

combobox in C# not getting populated

I have a windows forms app in C#. Platform is vS 2005.
Following is the piece of code:
namespace HostApp
{
public partial class Form1 : Form
{
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
comboBox2.Items.Add("Apples");
comboBox2.Items.Add("Oranges");
comboBox2.Items.Add("Grapefruits");
}
}
}
I run the app but the fruit names do not show up in the drop down of comboBox2. I am sure I am missing some line of code to "populate" the drop down with the entered values.
Any help would be much appreciated.
Thanks,
Viren
You add the items in the handler for the SelectedIndexChanged event. You need to move the code to InitializeComponent or another appropriate place.
Please check the following things:
You have added AutoPostBack="true" in the combo-box so that the selectedChange event is fired and post back happens.
Make sure you have nothung in ur Page load which refreshed the combo box. You can use IsPostBack to acheive loading of the values.
Your items are being added when the selected item is changed, but as there are no existing items this will never happen. Move those lines to the constructor for Form1 and it'll work.
The code you provided will only add items to comboBox2 when the selection changes in the control that is hooked up to comboBox2_SelectedIndexChanged.
There are two concepts at play here: Control Initialization/Databinding, and event handling.
The code you have written essentially says "If somebody selects something new in the combo box, add these 3 options to the combo box". That would happen every time the selected index changes in the combo box. This, of course, assumes you have even hooked up this event handler to the combo box to begin with. This is event handling.
What you are probably trying to do is initialize the control. This happens when you load the page and want to setup the initial options available in your page controls. Using the Init or Load event is probably where you want to setup the choices in your control. This is also when you would initialize your event handlers to say "When something happens, do this".
Move the code to the Page_Load event ...
The SelectedIndexChanged only fires when the ComboBox index has changed AND AutoPostBack = True.
EDIT: Sorry, it's a Form, I was thinking web ... move to Form_Load
For people having difficulties with autopostback and viewstate, beware of the page_load event.
If have been getting on this page alot when trying to google, so that's the reason i'll post it here.
If you fill your dropdownlist (or any other control) in the page_load method, be sure to write an extra control is there is a postback (triggered when changing value of a dropdownlist).
If you don't make that control, your controls will be refilled.
That mistake took me a while to figure out.
So what i'm saying is
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//fill your controls here
}
}

Categories