为组合框中显示的项目弹出自定义项目渲染器
我在组合框中使用自定义项目渲染器来显示自定义绘图,而不是默认文本标签。
这适用于下拉列表,但显示的项目(列表关闭时)仍然是我的对象的文本表示形式。
有没有办法让显示的项目与下拉菜单中的项目呈现方式相同?
默认情况下,你不能这样做。 但是,如果扩展ComboBox,则可以轻松添加此功能。 下面是一个简单的例子,它是一个粗略的版本,可能需要测试/调整,但它显示了你可以如何实现这一点。
package
{
import mx.controls.ComboBox;
import mx.core.UIComponent;
public class ComboBox2 extends ComboBox
{
public function ComboBox2()
{
super();
}
protected var textInputReplacement:UIComponent;
override protected function createChildren():void {
super.createChildren();
if ( !textInputReplacement ) {
if ( itemRenderer != null ) {
//remove the default textInput
removeChild(textInput);
//create a new itemRenderer to use in place of the text input
textInputReplacement = itemRenderer.newInstance();
addChild(textInputReplacement);
}
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
if ( textInputReplacement ) {
textInputReplacement.width = unscaledWidth;
textInputReplacement.height = unscaledHeight;
}
}
}
}
我尝试了上述解决方案,但发现当关闭组合框时,selectedItem没有显示。 需要额外的代码行来将itemRenderer数据属性绑定到selectedItem:
if ( !textInputReplacement ) {
if ( itemRenderer != null ) {
//remove the default textInput
removeChild(textInput);
//create a new itemRenderer to use in place of the text input
textInputReplacement = itemRenderer.newInstance();
// ADD THIS BINDING:
// Bind the data of the textInputReplacement to the selected item
BindingUtils.bindProperty(textInputReplacement, "data", this, "selectedItem", true);
addChild(textInputReplacement);
}
}
我已经进一步扩展了Dane的代码。 在某些情况下,点击没有打开我的渲染器的下拉框,我注意到正常的Flex组合框皮肤没有触发。 因此,在replaceTextInput()中,我添加了一些额外的事件侦听器,并保存对用于显示外观的ComboBox按钮的引用。 现在它的行为就像普通的ComboBox一样。
代码如下:
package
{
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import mx.binding.utils.BindingUtils;
import mx.controls.Button;
import mx.controls.ComboBox;
import mx.core.IFactory;
import mx.core.UIComponent;
import mx.events.DropdownEvent;
/**
* Extension of the standard ComboBox that will use the assigned 'itemRenderer'
* for both the list items and the selected item.
*
* Based on code from:
* http://stackoverflow.com/questions/269773/flex-custom-item-renderer-for-the-displayed-item-in-the-combobox
*/
public class ComboBoxFullRenderer extends ComboBox
{
protected var textInputReplacement:UIComponent;
private var _increaseW:Number = 0;
private var _increaseH:Number = 0;
/**
* Keeps track of the current open/close state of the drop down list.
*/
protected var _isOpen:Boolean = false;
/**
* Stores a reference to the 'Button' which overlays the ComboBox. Allows
* us to pass events to it so skins are properly triggered.
*/
protected var _buttonRef:Button = null;
/**
* Constructor.
*/
public function ComboBoxFullRenderer() {
super();
}
/**
* Sets a value to increase the width of our ComboBox to adjust sizing.
*
* @param val Number of pixels to increase the width of the ComboBox.
*/
public function set increaseW(val:Number):void {
_increaseW = val;
}
/**
* Sets a value to increase the height of our ComboBox to adjust sizing.
*
* @param val Number of pixels to increase the height of the ComboBox.
*/
public function set increaseH(val:Number):void {
_increaseH = val;
}
/**
* Override the 'itemRenderer' setter so we can also replace the selected
* item renderer.
*
* @param value The renderer to be used to display the drop down list items
* and the selected item.
*/
override public function set itemRenderer(value:IFactory):void {
super.itemRenderer = value;
replaceTextInput();
}
/**
* Override base 'createChildren()' routine to call our 'replaceTextInput()'
* method to replace the standard selected item renderer.
*
* @see #replaceTextInput();
*/
override protected function createChildren():void {
super.createChildren();
replaceTextInput();
}
/**
* Routine to replace the ComboBox 'textInput' child with our own child
* that will render the selected data element. Will create an instance of
* the 'itemRenderer' set for this ComboBox.
*/
protected function replaceTextInput():void {
if ( !textInputReplacement ) {
if ( this.itemRenderer != null && textInput != null ) {
//remove the default textInput
removeChild(textInput);
//create a new itemRenderer instance to use in place of the text input
textInputReplacement = this.itemRenderer.newInstance();
// Listen for clicks so we can open/close the drop down when
// renderer components are clicked.
textInputReplacement.addEventListener(MouseEvent.CLICK, _onClick);
// Listen to the mouse events on our renderer so we can feed them to
// the ComboBox overlay button. This will make sure the button skins
// are activated. See ComboBox::commitProperties() code.
textInputReplacement.addEventListener(MouseEvent.MOUSE_DOWN, _onMouseEvent);
textInputReplacement.addEventListener(MouseEvent.MOUSE_UP, _onMouseEvent);
textInputReplacement.addEventListener(MouseEvent.ROLL_OVER, _onMouseEvent);
textInputReplacement.addEventListener(MouseEvent.ROLL_OUT, _onMouseEvent);
textInputReplacement.addEventListener(KeyboardEvent.KEY_DOWN, _onMouseEvent);
// Bind the data of the textInputReplacement to the selected item
BindingUtils.bindProperty(textInputReplacement, "data", this, "selectedItem", true);
// Add our renderer as a child.
addChild(textInputReplacement);
// Listen for open close so we can maintain state. The
// 'isShowingDropdown' property is mx_internal so we don't
// have access to it.
this.addEventListener(DropdownEvent.OPEN, _onOpen);
this.addEventListener(DropdownEvent.CLOSE, _onClose);
// Save a reference to the mx_internal button for the combo box.
// We will need this so we can call its dispatchEvent() method.
for (var i:int = 0; i < this.numChildren; i++) {
var temp:Object = this.getChildAt(i);
if (temp is Button) {
_buttonRef = temp as Button;
break;
}
}
}
}
}
/**
* Detect open events on the drop down list to keep track of the current
* drop down state so we can react properly to a click on our selected
* item renderer.
*
* @param event The DropdownEvent.OPEN event for the combo box.
*/
protected function _onOpen(event:DropdownEvent) : void {
_isOpen = true;
}
/**
* Detect close events on the drop down list to keep track of the current
* drop down state so we can react properly to a click on our selected
* item renderer.
*
* @param event The DropdownEvent.CLOSE event for the combo box.
*/
protected function _onClose(event:DropdownEvent) : void {
_isOpen = false;
}
/**
* When we detect a click on our renderer open or close the drop down list
* based on whether the drop down is currently open/closed.
*
* @param event The CLICK event from our selected item renderer.
*/
protected function _onClick(event:MouseEvent) : void {
if (_isOpen) {
this.close(event);
} else {
this.open();
}
}
/**
* React to certain mouse/keyboard events on our selected item renderer and
* pass the events to the ComboBox 'button' so that the skins are properly
* applied.
*
* @param event A mouse or keyboard event to send to the ComboBox button.
*
*/
protected function _onMouseEvent(event:Event) : void {
if (_buttonRef != null) {
_buttonRef.dispatchEvent(event);
}
}
} // end class
} // end package
链接地址: http://www.djcxy.com/p/5901.html
上一篇: Flex custom item renderer for the displayed item in the combobox
