Assume we have a Combobox in a winforms application which its items bound to a Bindingsource.
I need to fire an event when the user changes the selected item in the combobox.
Should I handle the combobox.selectedindexchanged event or bindingsource.currentchanged event. Which is better in case of performance or anything else?
I've searched a lot to find an article or something about it, but can't find something straight and clear. I appreciate any suggestion or workaround.
UPDATE
I need to call a function base on the selected object ID after user select an Item from combobox. (ID is accessible from both Combobox1.SelectedValue and bindingSource1.Current.ID). In this case which event shouldI choose?
If you wish to handle event when end user selects any item in UI then you should go with combobox.selectedindexchanged because bindingsource.currentchanged can be triggered for number reasons such as mentioned here on MSDN blog, BindingSource.CurrentChanged Event so in case, you need to handle an event for any of the reason mentioned in MSDN then it will unnecessarily go through logic you might have coded for selection change event. Your code should be specific, while handling events.
If a ComboBox is bound to a BindingSource you usually leave it at that. If you do need to tap into events you're better off creating more properties in the Business Object. For example say you want to disable a button if the combobox is Index Value == 0, simply create a property in the Business Object that the Enabled property of the Button is bound to, eg:
public virtual bool IsFunctionEnabled
{
get { return (An_Items_SelectedIndex > 0); }
}
If you really need to do stuff in the ComboBox's selected index change event I would lean towards doing it in the Presentation Tier as I don't recommend mucking with binding source controls or their events.
The best solution is handling everything in your Business Objects and binding your controls via BindingSources. Doing any logic in the Presentation Tier makes it hard to test and changing anything in the BindingSources add a lot of testing.
After all, I am getting to know it should be better to use Combobox.SelectedIndexChanded event, because I am interacting with a user and looking for a response from UI. Although here the events do the same for me, but Bindingsource.CurrentChanged event can be used in case I wanted to track the current object changes from anywhere like a list change or something, not exactly the UI. Its better to use combobox events here I believe.
Related
Ok. This seems like an incredibly basic use case but fore some reason I am having an issue finding a common solution across control types.
Heres the use case:
A form is presented to the user with any editable controls. (Text box, combo, grid etc.).
The user edits a value in the control and tabs out.
Expectation is that I can wire to an event like Lost Focus and do "foo" with the changed value.
The user then gives focus back to the control and tabs out without making an edit.
Expectation is that whatever event I am wired to I can check if the value has been changed.
Is there one common event across controls that will only fire when the user has finished editing( such as tab out or enter ) and allow me to check previous state vs. current state?
Jason, you may want to look into Binding and DependencyProperties in WPF instead of tracking events in your form. You would bind a class to your form which exposes properties to be changed. Using DependancyProperties a single event is fired called "PropertyChanged".
Unfortunately is is a broad topic, but you will really get the full benefit of the WPF programming model. Searches on "dependency properties in wpf" will give you some good examples.
I think maybe this is Focus issue. There exist two different focus types: keyboard focus and logical focus. The the control that has keyboard focus is the one that has the caret, in what the user press a key and the control process that input. The a control may have the logical focus but not having the keyboard focus. Please check this in the MSDN article "Input Overview". About the other question, maybe you could process the TabControl.SelectedItemChanged for taking the event when a tab item selection changed.
Hope this is helpful to you...
What you may be interested in is implementing INotifyPropertyChanging (not just INotifyPropertyChanged).
As noted in the answer of this question, the INotifyPropertyChangING does not prevent you from changing a value, but to detect WHEN something DOES change, and what it's new value is going to be.
Hope it helps in your solution needs.
As the previous answers suggested, you would be better off by implementing a view - viewmodel structure, with your viewmodel having implemented INotifyPropertyChanged, and thus allowing you to bind to properties that will announce their changes to the UI.
If you don't want to do this, you can eventually subscribe on your input elements to the PreviewKeyUp event, check if the Tab key has been pressed and proceed from there.
I've been looking into MVVM lately, and after I discovered Caliburn.Micro things have been pretty swell; I'm still in the early learning stages, but I belive I have an OK feel for the MVVM basics.
I'm bumping into issues with WPF DataGrid, though - and it's pretty much the same issues that I had with WinForms DataGridView: how the heck do you handle CanUserAddRows=true in-grid item adding cleanly?
I obviously don't want to add DataGrid-specific hacks to my ViewModel, since it ideally should be repurposable for other View controls. At the same time, I'd like to be able to get a notification when a new row item has been added, so I can persist it right away.
I'm binding the DataGrid to a BindableCollection<FooModel> FooItems - with a clean MVVM design, if I understand things correctly, I would be able to handle FooItems.CollectionChanged and react to Add/Remove events. However, the DataGrid fires the Add event as soon as a default-constructed item is added - this is obviously not the right time to persist the object!
After a lot of googling and digging through StackOverflow, I'm getting the impression that DataGrid is being utterly retarded in how it's firing the Add/Remove events. People who use it with CanUserAddRows=true seem to only work on in-memory collections, where people who persist data seem to use separate input fields + buttons Commands to add new items.
My FooModel implements INotifyPropertyChanged but not IEditableObject - as far as I can tell that shouldn't be the problem, though, since IEO seems related to property edit/undo, whereas my problem is with when the Add event is fired...
So, what do you do to handle in-grid editing cleanly?
It sounds like the WPF DataGrid behaves in much the same way as the WinForms DataGridView, in that it creates an item in the data source as soon as the user begins entering into the 'new row'. Subsequent edits would result in changes to the properties of the new item in the collection.
If you were to use BindingList<FooModel> instead, you get the additional event called ListChanged - providing your FooModel type implements INotifyPropertyChanged, the event will fire when the properties of the item are changed (as well as when items are added/removed from the collection).
Hope this helps!
I know it's been a long time since this was asked but I'm working on something similar now and thought I'd post my solution. You may consider this a hack but it's the best way I could figure to get DataGrid to tell me when it was out of edit mode (for my own reasons).
I looked through the DataGrid code and found the closest thing to end edit I could override, which turns out to be OnExecutedCommitEdit(). I then just raise an event after that function finishes. When my event subscriber gets called DataGrid is no longer in edit mode and I can do whatever I need to it. Here's the code:
/// <summary>
/// Deriving a new DataGrid because we need an event to tell us when editing is complete.
/// </summary>
public class DataGridMod : DataGrid
{
public delegate void EditCompletedDelegate();
public EditCompletedDelegate EditCompleted;
public DataGridMod() { }
protected override void OnExecutedCommitEdit(ExecutedRoutedEventArgs e)
{
base.OnExecutedCommitEdit(e);
if (EditCompleted != null)
EditCompleted();
}
}
I have application full of various controls databound to my classes. I would like to ask user "You are closing application and you made some changes. Do you want to save your changes?". For this I need to recognize that user made any changes.
How to catch user made changes in databound controls? Is textBoxXXX_TextChanged the only way to do this?
Thanks in advance for all your answers.
It depends on the datasource; for example DataTable and DataSet sources contain the GetChanges() methods which allow you to easily see if rows have been added/removed/modified. Other data sources will have their own implementations, if any. If there is no implementation then it's up to you to determine how to check for those changes.
In any event this is something you should do at the data-level, not the UI (by watching for "changed" events). Watching events doesn't scale beyond a couple controls and maintenance can be iffy.
Update: Not sure why I didn't think of it, but a second option is to add a BindingSource to your UI object and use it as a databinding proxy (your UI controls databind to the BindingSource and the BindingSource binds to the real datasource). It provides a better approach than handling all your individual "Control_Changed" events, and requiring rework of your other layers (esp. if they aren't custom data-types).
You need to provide custom logic for that, there's not really an automatic way of doing this. As I see it there are several options:
At the start of the editing, save a copy of the original data object, and when you need to check, compare the current object with the saved one. The comparison can be custom (field by field) or semi-automatic by use of serialization (compare the serialized forms) - if it is serializable.
In each of your data object's property set accessors, test for a change in value and mark the object as 'dirty'.
As been discussed, there are many ways to do this depending on how granular you want to get.
A relatively easy way using client side javascript would be to do something like the following:
Hook into the onchange events of the form elements. You could do this dynamically on page load using javascript/DOM.
When the onchange error handler is called, you could set a page level variable: pageHasChanged = true;
Hook into the page's beforeonunload event (occurs when the user tries to navigate away from the page) and check the pageHasChanged variable to see if any changes were made. If changes were made you could alert the user.
This doesn't give you the detail of what changed, but would be fairly easy to modify to track which form elements changed.
I want to understand event cycles. I have a form with a grid and textboxes. It has a grid, bound to DataTable, and textboxes bound to same table too. I'm trying to debug something and need to know how to identify ALL events fired in the form to see what may solve an issue for me.
Anyhow, unless I explicitly subclass every class on my form, and override / attach to every event to my own event handlers, how can I get / listen to all events being fired during a certain action... Such as changing a "Selected" road in a DataGridView. It obviously updates its own "CurrentRow"... I need to know what / how to maybe FORCE a re-loading of SAME CurrentRow.
Reason: during a form level "Edit Mode", and I change the content in another "Textbox" control, and reject changes, I need it to simulate the current "Record" is reloaded to go back to its original values.
You could fire up a profiler and look at the method call tree.
Is there an ItemActivated event (like in Windows Forms) in the WPF ListBox or ComboBox controls? I can't see one.
It seems crazy for there not to be some event doing the same kind of thing - so does it just go by another name? If not, is there another easy way to do it? I've seen various blog posts about this but they all seem to involve subclassing the control and other things like that. I'm sure the WPF designers realised this was pretty much the most common thing that is done with a ListBox or ComboBox!
I'm basically looking for an event which will fire when the item is activated, telling me which item has activated and allowing me to access the properties of that item.
from what I understand of your description, you want to look at the SelectedItem (individual) and SelectedItems (a collection) properties. Additionally, there should be a SelectionChanged event (though I'm not certain about that naming there).