Jump to content
  • Status: Open
  • Priority: Major
  • Resolution: Unresolved
  • Platform: Android
  • Affects version: 1.16.1.0

При выборе значения из списка подсказок, когда их несколько и только не самую первую (точнее не "нулевую") возникает ошибка : "Значение [index] не попадает в требуемый диапазон [0, 0]". Index в данном случае принимает число, которое является индексом по порядку в списке (т.е. для второго значения в списке это будет 1, для 3-го - 2 итд).

Примерчик набросал, можно воспроизвести.

20230828.zip


User Feedback

Recommended Comments

  • Administrators

Добрый вечер,

Что вводить в поле ввода? чтобы было больше чем одна строка в списке

  • Administrators

Любопытно. Ошибка связана с тем, что при выборе элемента из списка происходит следующее:

  1. Вначале выполняется подстановка текста, что приводит к вызову события OnChanging.
  2. В OnChanging вы формируете список элементов заново.
  3. Вызывается событие OnSuggestionSelected, где уже список для подстановки другой.
  • Administrators

Самое интересно, что так работает Андроид. У него явно нарушение причинно-следственной связи 🙂 

image.png

dervish00

Active subscription
(edited)
9 часов назад, Yaroslav Brovin сказал:

Самое интересно, что так работает Андроид. У него явно нарушение причинно-следственной связи 🙂 

Звучит неутешительно ))) Думаю, от гугла долго придётся ждать исправления.

Попробую во время обработки занилить обработчик события OnChanging

 

PS. Не помогло.

Edited by dervish00

dervish00

Active subscription
procedure TFormMain.fgAutoCompleteEdit1Changing(Sender: TObject);
begin
   if fgAutoCompleteEdit1.Text.Length = 2 then begin
      FillSuggestionsList;
      fgAutoCompleteEdit1.Filtered := True;
   end
   else if fgAutoCompleteEdit1.Text.Length < 2 then begin
      fgAutoCompleteEdit1.Filtered := False;
      fgAutoCompleteEdit1.Suggestions.ClearAndResetID;
   end;
end;

procedure TFormMain.FillSuggestionsList;
var
   i : integer;

begin
   fgAutoCompleteEdit1.Suggestions.ClearAndResetID;
   GetListSuggestions(ListTest, fgAutoCompleteEdit1.Text);
   if ListTest.Count > 0 then begin
      fgAutoCompleteEdit1.Suggestions.BeginUpdate;
      for i := 0 to ListTest.Count - 1 do
         fgAutoCompleteEdit1.Suggestions.Add(ListTest[i].text).Id := ListTest[i].id.ToString;
      fgAutoCompleteEdit1.Suggestions.EndUpdate;
   end;
end;

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

dervish00

Active subscription
Спойлер
unit Form.Main;

interface

{$SCOPEDENUMS ON}

uses
  System.Types, System.Classes, FGX.Forms, FGX.Forms.Types, FGX.Controls, FGX.Controls.Types, FGX.Layout, 
  FGX.Layout.Types, FGX.ComboBox, FGX.AutocompleteEdit.Types, FGX.Edit,
  FGX.AutoCompleteEdit, System.Generics.Collections;

type
  TTestAutoCompleated = record
     id : integer;
     text : string;
  end;

  TFormMain = class(TfgForm)
    fgAutoCompleteEdit1: TfgAutoCompleteEdit;
    procedure fgFormCreate(Sender: TObject);
    procedure fgFormDestroy(Sender: TObject);
    procedure fgAutoCompleteEdit1Changing(Sender: TObject);
  private
    { Private declarations }
    ListTest : TList<TTestAutoCompleated>;
    FSavedText : string;
    procedure FillSuggestionsList;
  public
    { Public declarations }
  end;

var
  FormMain: TFormMain;

const
   DBModel : array[0..9] of TTestAutoCompleated = (
      (id :  1; text : 'а'),
      (id :  2; text : 'аб'),
      (id :  3; text : 'абв'),
      (id :  4; text : 'абвг'),
      (id :  5; text : 'абвгд'),
      (id :  6; text : 'абвгде'),
      (id :  7; text : 'абвгдеж'),
      (id :  8; text : 'абвгдежз'),
      (id :  9; text : 'абвгдежзи'),
      (id : 10; text : 'абвгдежзик')
   );

   LengthTextForShowSuggestion = 2;

implementation

{$R *.xfm}

uses
  System.SysUtils,
  FGX.Application,
  FGX.Dialogs,
  FGX.Log;

procedure GetListSuggestions(var ListSuggestions : TList<TTestAutoCompleated>; Pattern : string);
var
   lTest : TTestAutoCompleated;
   i : integer;

begin
   ListSuggestions.Clear;
   for i := Low(DBModel) to High(DBModel) do
      if AnsiPos(AnsiUpperCase(Pattern), AnsiUpperCase(DBModel[i].text)) > 0 then begin
         lTest.id := DBModel[i].id;
         lTest.text := DBModel[i].text;
         ListSuggestions.Add(lTest);
      end;
end;

procedure TFormMain.fgAutoCompleteEdit1Changing(Sender: TObject);
var
   WasBackspace : boolean;

begin
   WasBackspace := ((fgAutoCompleteEdit1.Text.Length < FSavedText.Length) and (fgAutoCompleteEdit1.Text.Length > LengthTextForShowSuggestion));
   FSavedText := fgAutoCompleteEdit1.Text;
   if (fgAutoCompleteEdit1.Text.Length = LengthTextForShowSuggestion) or WasBackspace then begin
      FillSuggestionsList;
      fgAutoCompleteEdit1.Filtered := True;
   end
   else if fgAutoCompleteEdit1.Text.Length < LengthTextForShowSuggestion then begin
      fgAutoCompleteEdit1.Filtered := False;
      fgAutoCompleteEdit1.Suggestions.ClearAndResetID;
   end;
end;

procedure TFormMain.FillSuggestionsList;
var
   i : integer;

begin
   fgAutoCompleteEdit1.Suggestions.ClearAndResetID;
   GetListSuggestions(ListTest, fgAutoCompleteEdit1.Text);
   if ListTest.Count > 0 then begin
      fgAutoCompleteEdit1.Suggestions.BeginUpdate;
      for i := 0 to ListTest.Count - 1 do
         fgAutoCompleteEdit1.Suggestions.Add(ListTest[i].text).Id := ListTest[i].id.ToString;
      fgAutoCompleteEdit1.Suggestions.EndUpdate;
   end;
end;

procedure TFormMain.fgFormCreate(Sender: TObject);
begin
   inherited;
   ListTest := TList<TTestAutoCompleated>.Create;
   FSavedText := '';
end;

procedure TFormMain.fgFormDestroy(Sender: TObject);
begin
   FreeAndNil(ListTest);
   inherited;
end;

end.

 

Изменил для правильного отслеживания ситуации, когда уменьшаем длину текста. Работает.

  • Administrators

Самое простое решение - это завернуть код заполнения подсказок в TThread.ForceQueue. Тем самым будет гарантироваться вызов заполнения списка после выбора элемента.

dervish00

Active subscription

А вот с этого момента поподробнее )))

Ярослав, нарисуйте скелет обёртки?

  • Administrators
TThread.ForceQueue(nil, procedure 
begin
// Тут заполняете список
end);

Вызываете этот код из события OnChanging.

dervish00

Active subscription

Спасибо. Попробую.

dervish00

Active subscription
(edited)
procedure TFormMain.fgAutoCompleteEdit1Changing(Sender: TObject);
begin
   TThread.ForceQueue(nil, procedure
      begin
         if fgAutoCompleteEdit1.Text.Length >= LengthTextForShowSuggestion then
            FillSuggestionsList;
      end);
end;

 

Попробовал. Нет, работает не как ожидается. Список подхватывает неправильно с опозданием и вываливается с ошибкой диапазона. 

Edited by dervish00

Create an account or sign in to comment

Recently Browsing 0

  • No registered users viewing this page.