Перейти к содержанию
Fire Monkey от А до Я
  • 0

После активации TSearchBox не возвращается индекс нового добавленого элемента


Belov.V.

Вопрос

Столкнулся с такой ситуацией.
 
1) Заполняем TListBox;
2) Пользуемся поиском через TSearchBox;
3) Очищаем TSearchBox;
4) При попытке добавить любой новый элемент в TListBox, всегда возвращается индекс добавленного элемента "-1".
 
Накидал пример для экспериментов, упростив до безобразия (прикрепляю).
 
Как восстановить возможность получать индекс добавленного элемента?
 

0_116754_6fc8cf12_orig.png

Project1.zip

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
  • Администраторы

К сожалению этот вопрос до сих пор не имеет однозначного ответа.

А вопрос такой, какой индекс итема должен вернуться?

  1. Индекс в отфильтрованном списке
  2. или индекс в исходном?

В текущей реализации возвращается индекс в отфильтрованном списке. Поэтому если добавляемый итем не попадает под условие фильтра, то функция возвращает -1. А если попадет, то она вернет индекс в отфильтрованном списке.

Ссылка на комментарий
  • 0

К сожалению этот вопрос до сих пор не имеет однозначного ответа.

А вопрос такой, какой индекс итема должен вернуться?

  1. Индекс в отфильтрованном списке
  2. или индекс в исходном?

В текущей реализации возвращается индекс в отфильтрованном списке. Поэтому если добавляемый итем не попадает под условие фильтра, то функция возвращает -1. А если попадет, то она вернет индекс в отфильтрованном списке.

 

Индекс в отфильтрованном не возвращает ни в каком варианте.

 

- Если список не упорядочен (ListBox1.Sorted:=False), то возвращается индекс последнего добавленного по порядку (0,1,2,3 и т.д.). Из вопроса выше - 2-й вариант.

- Если список упорядочить (ListBox1.Sorted:=True), по возвращается индекс в упорядоченном списке. Тут вроде все корректно работает.

Но это варианты с сортировкой.

 

Если же мы устанавливаем значение TSearchBox, который действительно в данном случае выступает как фильтр, то при добавлении нового итема, вне зависимости от того попадает в фильтр или нет, всегда получаем "-1". В общем-то для упрощения я указал в п.3 (Очищаем TSearchBox). При пустом фильтре все равно "-1".

 

ListBox1.Count  тоже начинает "глючить". Не показывает верное значение, пока повторно не установишь /сбросишь значение в TSearchBox. 

 

Пробовал после использования TSearchBox вообще этот объект "убивать". Все равно последствия его применения остаются.

Ссылка на комментарий
  • 0

С удалением строк из Button2Click, после изменения TSearchBox (не важно, в каком состоянии его оставить), тоже ошибки начинают возникать. Причем там вообще жестко.

 

Помогает тупое передергивание значение фильтра, пусть даже он был пустой:

 

var s : string;
begin
  ListBox1.Items.Delete(0);
  //
  s := SearchBox1.Text;
  SearchBox1.Text := s+'`';
  SearchBox1.Text := s;
end;
 
Примерно таким путем можно бороться с ошибкой при добавлении итемов (убрать сортировку, добавить итем, дернуть фильтр, последняя строка наша добавленная, восстанавливаем состояние на момент "до добавления"), но как-то все это.... стыдновато за такой код. :-(
Ссылка на комментарий
  • 0

Готового решения на просторах интернета не нашел. То, что напридумывал сам, оформил в виде хелпера к TListBox. Может кому пригодится.

Реализовал только необходимые мне методы. И только для режима MultiSelectStyle=None

Самое главное, что так индекс возвращается корректно.

unit ListBoxHelper;

interface

uses FMX.Controls, FMX.Types, System.SysUtils, FMX.ListBox, FMX.SearchBox;


// Создаем Helper для класса TListBox
type
  TListBoxHelper = class helper for TListBox
    function ResetFilter : string;                                // возвращает старый фильтр
    function GetSearchBox : TSearchBox;                           // возвращает SearchBox
    function AddAndClearSelect(const S : string) : integer;       // добавить, ничего не выбирать, фильтр очистить
    function AddAndSelect(const S : string) : integer;            // добавить, выбрать, фильтр очистить
    function AddAndSaveOldSelect(const S : string) : integer;     // добавить, сохранить выбор, фильтр очистить
    function AddAndSaveOldView(const S : string) : integer;       // добавить, сохранить выбор и фильтр, вернуть номер добавленного в отфильтрованном списке, или -1 если не попадает в фильтр
    procedure DeleteItem(const i : integer = -1);                 // удалить по индексу. если индекс не указан то удалить выбранный
  end;
implementation


function TListBoxHelper.GetSearchBox : TSearchBox;
var
  Child     : TControl;
  FxmChild  : TFmxObject;
begin
  Result := nil;
  for Child in self.Controls do
    for FxmChild in Child.Controls do
      if FxmChild is TSearchBox then Exit( TSearchBox( FxmChild ) );
end;

function TListBoxHelper.ResetFilter : string;
var
  s   : TListBoxItem;
  sb  : TSearchBox;
begin
  Result := EmptyStr;
  s := Selected;
  sb := GetSearchBox;
  if Assigned( sb ) then begin
    Result  := sb.Text;
    sb.Text := EmptyStr;
  end;
  if Assigned( FilterPredicate ) then FilterPredicate := nil;
  if Assigned( s ) then ItemIndex := s.Index;
end;

function TListBoxHelper.AddAndClearSelect(const S : string) : integer;
begin
  ClearSelection;
  ResetFilter;
  Result := Items.Add( s );
end;

function TListBoxHelper.AddAndSelect(const S : string) : integer;
begin
  Result := AddAndClearSelect( s );
  if Result <> -1 then ItemIndex := Result;
end;

function TListBoxHelper.AddAndSaveOldSelect(const S : string) : integer;
var
  sel   : TListBoxItem;
begin
  sel := Selected;
  Result := AddAndClearSelect( s );
  if Assigned( sel ) then ItemIndex := sel.Index
end;

function TListBoxHelper.AddAndSaveOldView(const S : string) : integer;
var
  sb          : TSearchBox;
  iSel, iNew  : TListBoxItem;
  flt         : string;
begin
  iSel := Selected; iNew := nil;
  ClearSelection;
  sb := GetSearchBox;
  flt := ResetFilter;
  //
  Result := Items.Add( s );
  if Result <> -1 then iNew := ItemByIndex( Result );
  //
  if flt <> EmptyStr then begin
    sb.Text := flt;
    if Assigned( iNew ) then Result := iNew.Index;
  end;
  if Assigned( iSel ) then ItemIndex := iSel.Index;
end;

procedure TListBoxHelper.DeleteItem(const i : integer = -1);
var
  sb          : TSearchBox;
  flt         : string;
  iSel, iDel  : TListBoxItem;
begin
  if i > Count-1 then Exit;
  sb := GetSearchBox;
  if i > -1 then begin
      iSel := Selected;
      iDel  := ItemByIndex( i );
  end
  else begin
      iSel  := nil;
      iDel := Selected;
  end;
  flt := ResetFilter;
  if Assigned( iDel ) then Items.Delete( iDel.Index );
  //
  if flt <> EmptyStr then sb.Text := flt;
  if Assigned( iSel ) then ItemIndex := iSel.Index;
end;

end.

Еще на XE7 есть глюк в режиме Sorted := True, при добавить одинаковые значения (или несколько одинаковых) и сразу выделении одного через IntemIndex.

Но пока на выявление закономерностей и борьбу нет времени.

ListBoxHelper.zip

Изменено пользователем Belov.V.
Ссылка на комментарий
  • 0

Не могу представить себе ситуации когда для текущей реализации листбокса понадобится поиск. Ведь листбокс жутко подлагивает если в нем много элементов, да что уж там, после 30 уже начинается. ListView наше все...

Ссылка на комментарий
  • 0

Не могу представить себе ситуации когда для текущей реализации листбокса понадобится поиск. Ведь листбокс жутко подлагивает если в нем много элементов, да что уж там, после 30 уже начинается. ListView наше все...

 

Соглашусь с тем, что он действительно очень глючный. И без поиска, достаточно Sorted. Но иногда с ним проще.

Ссылка на комментарий
  • 0

 

Но иногда с ним проще.

чем проще?

 

 

Я за себя говорю. Давайте не будем углубляться в этот вопрос.

Тема про ошибку, которая существует. Если можете подсказать, как побороть ошибочное двойное выделение двух итемов при включенном sorted буду необычайно благодарен.

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...