Flex Datagrid Itemeditor: Показать метку выбора, но получить значение при фиксации
(РЕДАКТИРОВАТЬ: см. Мой ответ, представленный ниже в качестве возможного решения)
У меня есть сетка данных, где в каждой колонке данных используются разные элементы вывода. Одним из этих средств визуализации в одном из столбцов является компонент List, полный значений. Текст, показанный в компоненте списка, является метками его поставщика данных.
То, что я хотел бы сделать, это сделать элемент списка столбцов компонента List как itemeditor. Это означает, что пользователь нажимает на ячейку в столбце, и появляется список значений (НЕ выпадающий список). Затем они могут выбрать несколько значений из компонента списка. Когда они щелкают из компонента List, в столбце отображаются выбранные значения.
Когда они СОХРАНЯЮТ свой выбор (с помощью кнопки сохранения вне рассматриваемой сетки данных), я хотел бы сослаться на эти данные, чтобы определить, какой выбор они сделали - ОДНАКО - вместо метки, я хотел бы получить число, связанное с этим. этикетка. Я делаю это с XML:
<colors>
<color label="Green" value="1"/>
<color label="Yellow" value="2"/>
<color label="Red" value="3"/>
</colors>
Теперь часть itemeditor великолепна, так как отлично работает для визуального просмотра вашего выбора после того, как вы нажали за пределами ячейки. Однако я хотел бы определить значение выбранного цвета ("3") и сделать это для каждого значения, выбранного в этом списке.
Это должно быть определено естественным образом с помощью следующего столбца данных (CheckList - это просто список, который допускает множественный выбор без удержания клавиши CTRL) с использованием данного поставщика данных для этого столбца:
<colorData chosenColors=''/>
Вот пример кода:
<mx:DataGridColumn dataField="@chosenColors" editorDataField="colors" headerText="Colors" width="200" wordWrap="true">
<mx:itemEditor>
<fx:Component>
<s:MXDataGridItemRenderer focusEnabled="true" height="22" >
<fx:Script>
<![CDATA[
public function get colors():String {
var str:String = new String;
for(var i:int=0;i < colorList.selectedItems.length; i++){
if(i > 0){
str += ",\n";
}
str += colorList.selectedItems[i].@label;
}
return str;
}
]]>
</fx:Script>
<r:CheckList id="colorList"
dataProvider="{parentApplication.colors}"
labelField="@label" width="100%" height="150"/>
</s:MXDataGridItemRenderer>
</fx:Component>
</mx:itemEditor>
</mx:DataGridColumn>
Однако это просто заменяет XML следующим, если, скажем, были выбраны зеленый и красный:
<colorData chosenColors=' Green, Red'/>
Вместо этого я хотел бы, чтобы результирующий XML был:
<colorData chosenColors=' 1, 3'/>
Пожалуйста, дайте мне знать, как я могу это сделать - встроенный рендер или нет, другая реализация и т. Д. Спасибо за вашу помощь!
2 ответа
Попробуйте это поможет вам.
Вместо того, чтобы получать текст метки из selectedItems получить value
значение атрибута, например, @value. Так что теперь стать <colorData chosenColors='1, 3'/>
,
public function get colors():String {
var values:Array = [];
for(var i:int=0;i < colorList.selectedItems.length; i++){
values.push(colorList.selectedItems[i].@value.toString()); //Note here
}
return values.toString();
}
1, 3 также отображаются в сетке. Я не уверен, что вы ожидаете на уровне пользовательского интерфейса. Тем не менее, если вы хотите отобразить цвет как зеленый, красный на уровне пользовательского интерфейса, но в то же время вам нужно сохранить значение соответствующего узла. В случае, если создать еще один атрибут в XML, как
<colorData chosenColors='Green, Red' chosenValueColors='1,3' />.
Здесь selectedColors для отображения цели и selectedValueColors для базы данных может или для других целей. Теперь вы можете ожидать значения из атрибута selectedValueColors из XML.
На основании комментариев
Чтобы выполнить ваше требование, вам нужно override data getter/setter
метод в itemRenderer или вы можете использовать dataChange Event.
override public function get data():Object
{
return super.data;
}
override public function set data(value:Object):void
{
super.data = value;
if(!value)
return;
var selectedValues:Array = value.@chosenColors.toString().split(","); //get selected value in array
var selectedIndices:Vector.<int> = new Vector.<int>();
for (var i:int = 0, len:int = colorList.dataProvider.length; i < len; i++)
{
var color:XML = colorList.dataProvider[i] as XML;
if(selectedValues.indexOf(color.@value.toString()) > -1)
selectedIndices.push(i); //Store index of selected items
}
trace(selectedIndices.toString());
colorList.selectedIndices = selectedIndices;
}
public function get colors():String {
var values:Array = [];
for(var i:int=0;i < colorList.selectedItems.length; i++){
values.push(colorList.selectedItems[i].@value.toString());
}
return values.toString();
}
public function colorList_changeHandler(event:IndexChangeEvent):void
{
data.@value = colors; //IMPORT Commit the selected value to dataProvider.
}
Обратите внимание, что здесь мы слушаем событие изменения значения коммита в поставщике данных, например change="colorList_changeHandler(event)"
<r:CheckList id="colorList" change="colorList_changeHandler(event)"
dataProvider="{parentApplication.colors}"
labelField="@label" width="100%" height="150"/>
(РЕДАКТИРОВАТЬ: У этой реализации есть проблемы с Flex 4.11, когда поставщик данных иногда изменяется при использовании addItem - это может быть исправлено во Flex 4.12, но я не проверял. См. Комментарии ниже для разрешения.)
На самом деле я реализовал это немного по-другому, чем Раджа Джаганатан, однако я верю, что его ответ также поможет. Вот как я реализовал это исправление.
Опять же, было желание обновить XML dataProvider с помощью XML, а не только текста после завершения itemEditor. Я реализовал это, следуя примеру Adobe по этому URL-адресу (руководство по Flex 4.6): Примеры использования редакторов элементов MX с элементами управления на основе списка
Я использовал встроенный itemEditor для своего списка, который напоминал мой оригинальный вопрос. Разница была в том, что я вместо этого реализовал переопределение для функции данных (аналогично тому, что сделал Раджа). В функции данных (вызываемой при запуске itemEdit) я устанавливаю свои данные, но также устанавливаю selectedItems элемента управления списком на основе того, какие цвета были перечислены в моем XML. Это гарантировало, что элемент управления списком отображает цвета, которые уже были выбраны до взаимодействия с пользователем.
Затем, в конце itemEdit, я изменил свою функцию colors, чтобы установить временный атрибут в XML, который содержал идентификаторы, которые были выбраны в списке. Это гарантировало выбор пользователя (если он отличается от оригинала).
Теперь, вот где я боролся и где ответ Раджи может работать лучше. В функции colors я просто добавил выбранный XML в элементе управления списком в XML dataProvider. Это оказалось очень проблематичным, так как Flex не будет сохранять XML в dataProvider без предварительного его удаления, оставляя беспорядок в амперсандах и HTML-кодированном XML (т. Е. Мусор). Чтобы обойти это, я создал прослушиватель в сетке данных для события itemEditEnd. Этот слушатель вызвал функцию, аналогичную примеру Adobe, которая считывает выбранные идентификаторы цвета и заменяет закодированный мусор XML, который Flex дал мне, настоящим XML. Наиболее важной вещью в этом XML было немедленно вызвать protectDefault(), чтобы предотвратить переопределение того, что я сделал с поставщиком данных.
Выполнение этих действий дало мне возможность предоставить список пользователю, из которого можно выбирать, а затем показать пользователю его текущий выбор после того, как он переместился в другую ячейку в таблице данных. Это также позволило мне сохранить эти варианты для последующего извлечения, когда пользователь решил сохранить изменения в таблице на постоянной основе.
РЕДАКТИРОВАТЬ: Ниже этого пункта более глубокое объяснение того, как реализовать по-другому, чем пример Adobe.
Ссылка Adobe выше имеет некоторые проблемы при изменении editedItemEditor.data. Вместо этого я добавил функцию-обработчик события itemEditEnd в сетку данных следующим образом:
<mx:DataGrid id="dataGridSvcTypeReasons" height="100%" width="100%" dataProvider="{dataProvider}" editable="true" itemEditEnd="dataGrid_itemEditEndHandler(event)">
В функции обработчика я манипулировал исходными данными, а НЕ editedItemRenderer.data для примера Adobe:
protected function dataGrid_itemEditEndHandler(event:DataGridEvent):void{
if (event.reason == DataGridEventReason.CANCELLED){
// Do not update cell.
return;
}
event.preventDefault();
var data:Object = dataProvider.getItemAt(event.rowIndex);
// look to see if my list exists (if not, then this edit does not pertain to my list)
if(event.currentTarget.itemEditorInstance.hasOwnProperty("myList")){
var selectedItems:Vector.<Object>;
selectedItems = event.currentTarget.itemEditorInstance.myList.selectedItems;
delete data.colors;
data.appendChild(<colors/>);
if(selectedItems){
for each(var item:XML in selectedItems){
for(var i:int = 0; i < myList.dataProvider.length; i++){
if(myList.dataProvider[i].@value == item.@value){
data.colors.appendChild(new XML(myList.dataProvider[i]));
break;
}
}
}
}
}
}
Этот метод позволит избежать проблем с графическим интерфейсом, возникающих в результате разрушения editedItemRenderer, найденного в примере Adobe.