Does anyone know, is there any way to catch ItemClick Event in a Flex ComboBox (or anything similar). Maybe there's any trick .. :) I do realize, that I can customize it, but this not suits my case.
Thanks for your time :)
As you can see in mx:ComboBox sources, the function, creating the dropdown list, is private, the listener to ITEM_CLICK is private and the list itself is also private:
private var _dropdown:ListBase;
private function getDropdown():ListBase
{
// ...
_dropdown = dropdownFactory.newInstance();
// ...
_dropdown.addEventListener(ListEvent.ITEM_CLICK, dropdown_itemClickHandler);
// ....
}
private function dropdown_itemClickHandler(event:ListEvent):void
{
if (_showingDropdown)
{
close();
}
}
So you can not even extend ComboBox.
The only public thing is dropdownFactory, which theoretically can be overriden to somehow register the created dropdown list or create extended list. But the problem I see is that ComboBox is not the parent of dropdown list - PopupManager is. This can make dispatching (bubble) events quite difficult.
I think the following document will be helpful
ItemClick event in flex List
I found this solution. I just want a spark dropdownlist with itemClick event and without itemselect option (don't show selected item label on button)
[Event(name="itemClick", type="mx.events.ItemClickEvent")]
public class ItemClickDropDownList extends DropDownList
{
public function ItemClickDropDownList()
{
super();
}
override public function closeDropDown(commit:Boolean):void
{
super.closeDropDown(commit);
var e:ItemClickEvent = new ItemClickEvent(ItemClickEvent.ITEM_CLICK, true);
e.item = this.selectedItem;
e.index = this.selectedIndex;
dispatchEvent(e);
//Deselect item
this.selectedIndex = -1;
}
Related
Hello fellow coders of the night,
I am stuck with a moral dilemma (well not moral, but mostly i don't know what to do).
Suppose I have one button that can do several actions, depending on the menu item which is chosen.
Basically, I've imagined this
private void menuButtonActionPerformed(ActionEvent b)
ActionEvent a
if(a.getSource()==menuItem)
if(b.getSource()==button)
do this and that
Is this the correct way to do this? because if it is I'd have to add ActionListeners on the menuItem but I get stuck with some stupid error code somewhere!
Thanks in advance for helping me!
Post Scriptum : #David, I've tried this, however the initial condition isn't verified.
private void buttonValidateActionPerformed(java.awt.event.ActionEvent evt)
ActionListener l = (ActionEvent e) -> {
if(e.getSource()==menuItemAdd)
{
System.out.println("eureka!");
buttonSearch.setEnabled(false);
if (evt.getSource()==buttonValidate)
{
DataTransac dt = new DataTransac();
dt.addCoders("...");
}
}
if(e.getSource()==itemDelete)
{
DataTransac dt = new DataTransac();
dt.deleteCoders("...");
}
};
menuItemAdd.addActionListener(l);
itemDelete.addActionListener(l);
That won't work; your listener will get a different invocation for each time the listener is used -- so the event source will be either a button or a menu item for a single invocation.
You'll need to respond to the menu item with one ActionListener that stores state, and then separately handle the button action. You could do this with one listener, but I wouldn't; I'd do this:
private MenuItem selected;
private class MenuItemListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
// if you really want to have one listener for multiple menu items,
// continue with the .getSource() strategy above, but store some
// state outside the listener
selected = (MenuItem)event.getSource();
// you could alternatively have a different listener for each item
// that manipulates some state
}
}
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
// take conditional action based on selected menu item, as you describe
// in the question
}
}
void setup() {
JMenuItem first = /* ... */;
JMenuItem second = /* ... */;
MenuItemListener listener = new MenuItemListener();
first.addActionListener(listener);
second.addActionListener(listener);
JButton button = /* ... */;
button.addActionListener(buttonListener);
}
Generally speaking this is the preferred approach -- use a different listener for each semantic action, rather than one that introspects the source. Your code will be cleaner, simpler, and easier to understand.
For the same reasons, some people prefer to use anonymous classes for Java event listeners. Here's a Gist that shows several syntaxes: https://gist.github.com/sfcgeorge/83027af0338c7c34adf8. I personally prefer, if you are on Java 8 or higher:
button.addActionListener( event -> {
// handle the button event
} );
I am new to MVVM and Caliburn.Micro.
I am trying to do a simple application using Caliburn.Micro that has a combobox.
The combobox items are added dynamically when the program is running, the problem is that the combobox stops updating its content after the first item navigation.
In View:
The combobox is declared as follows:
<ComboBox x:Name="cmbProductList" />
In ViewModel:
I declare the following list for combobox items:
List<string> L = new List<string> { };
I am using the following method to fill combobox item:
public List<string> cmbProductList
{
get
{
return L;
}
set
{
L = value;
NotifyOfPropertyChange("cmbProductList");
}
}
And this command to add an item to this list:
L.Add(p1.ID.ToString());
The container you are using for your combobox items is not the proper one. List has no way of notifying the UI of its changes (items added or removed). Instead you need to use an ObservableCollection. Or even better, you can use BindableCollection that is Caliburn.Micro's customized version of ObservableCollection:
BindableCollection is a simple collection that inherits from ObservableCollection, but that ensures that all its events are raised on the UI thread as well.
http://caliburnmicro.com/documentation/introduction
Your property would look like this:
private BindableCollection<string> _cmbProductList;
public BindableCollection<string> cmbProductList
{
get
{
return _cmbProductList;
}
set
{
_cmbProductList = value;
NotifyOfPropertyChange("cmbProductList");
}
}
and of course its initialization would look like this:
_cmbProductList = new BindableCollection<string>();
The rest can stay unchanged.
I have a requirement in my program that the object bound (from ViewModel) in a Combobox is updated as soon as an item is selected in the combobox. Currently, the object only updates once the edit is committed by either pressing Enter or leaving the cell. The user does not want the extra step.
My thought would be to have the act of selecting an item in the combobox trigger the CommitEdit() method and then CancelEdit(). However, I cannot seem to find a way to hook into the SelectionChanged event for the DataGridComboBoxColumn as it is not available.
Other suggestions have been to listen in the viewmodel for a property change event but the property is not changed until the Cell Edit is finished.
Can anyone think of a way to cause the selection of a new item (index) in a DataGridCombobox to close the edit of the cell as if the user pressed Enter or left the cell?
NOTE: I cannot use .NET 4.5 due to customer limitations.
I've had similar issue but i just found out the solution using attached property, This may not exactly fix your problem but it will help in datagrid selection changed issue.
Below is the attached property and handler methods
public static readonly DependencyProperty ComboBoxSelectionChangedProperty = DependencyProperty.RegisterAttached("ComboBoxSelectionChangedCommand",
typeof(ICommand),
typeof(SpDataGrid),
new PropertyMetadata(new PropertyChangedCallback(AttachOrRemoveDataGridEvent)));
public static void AttachOrRemoveDataGridEvent(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
DataGrid dataGrid = obj as DataGrid;
if (dataGrid != null)
{
if (args.Property == ComboBoxSelectionChangedProperty)
{
dataGrid.SelectionChanged += OnComboBoxSelectionChanged;
}
}
else if (args.OldValue != null && args.NewValue == null)
{ if (args.Property == ComboBoxSelectionChangedProperty)
{
dataGrid.SelectionChanged -= OnComboBoxSelectionChanged;
}
}
}
private static void OnComboBoxSelectionChanged(object sender, SelectionChangedEventArgs args)
{
DependencyObject obj = sender as DependencyObject;
ICommand cmd = (ICommand)obj.GetValue(ComboBoxSelectionChangedProperty);
DataGrid grid = sender as DataGrid;
if (args.OriginalSource is ComboBox)
{
if (grid.CurrentCell.Item != DependencyProperty.UnsetValue)
{
//grid.CommitEdit(DataGridEditingUnit.Row, true);
ExecuteCommand(cmd, grid.CurrentCell.Item);
}
}
}
SpDataGrid is the custom control that i inherited from data grid.
I added below style in generic.xaml as i use the resourcedictionary for style (you can certainly add inside the datagrid).
<Style TargetType="{x:Type Custom:SpDataGrid}">
<Setter Property="Custom:SpDataGrid.ComboBoxSelectionChangedCommand" Value="{Binding ComboBoxSelectionChanged}"/>
</Style>
ComboBoxSelectionChanged is the command in my viewmodel. OnComboBoxSelectionChanged i commented the commitedit because in my case the values were already updated.
Let me know if anything is not clear or any questions. Hope this helps.
I am facing a weird situation here. I am unable to add tooltips, mouse (click,mouseover,mouseout) events to a runtime created button inside a container(HBox).
This init() function executes under creationComplete event.
private function init():void
{
for(var i:int=0;i<5;i++)
{
myButton = new Button();
myButton.id="mBtn"+i;
myButton.label="Test";
myButton.addEventListener(MouseEvent.CLICK,onDblClick);
camCont.addChildAt(myButton,i); //camCont is the HBox control
}
}
protected function onDblClick(event:MouseEvent):void
{
Alert.show("Click event works !!!");
}
When this application is executed, the 5 buttons are created, but click event is not fired. Can someone guide me where am i going wrong ?
Thanks.
you can try this code (this works!):
//Code
public function init():void{
var btn:Button = new Button();
btn.addEventListener(MouseEvent.CLICK, showAlert);
container.addChild(btn);
}
private function showAlert(event:Event):void{
Alert.show("CLICK!!!");
}
//MXML
<mx:HBox id="container"/>
You can try here. The source code is here.
I hope it will be helpful.
When a combobox is elected in the flex app, there is a quick flicker, then the combobox needs to be selected again in order to get the dropdown to open. After that, the dropdown works as expected, but only while selecting the control subsequent times while on the form. Reloading the form requires the double selection again. Any insights to how to clear this up would be very much appreciated.
The way I had to get around this issue was my creating a custom component that extends the ComboBox control that will set the ComboBox's List dataProvider at the same time as the ComboBox's dataProvider.
ComboBoxFix.as
package
{
import mx.controls.ComboBox;
public class ComboBoxFix extends ComboBox
{
public function ComboBoxFix()
{
super();
}
override public function set dataProvider(value:Object):void
{
super.dataProvider=value;
if(dropdown != null)
{
super.dropdown.dataProvider=value;
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number ):void
{
super.updateDisplayList (unscaledWidth, unscaledHeight);
if (dropdown != null)
{
dropdown.width = unscaledWidth;
}
}
}
}