.net - recordar - Cómo obtener de forma asíncrona datos Autocompletar para un cuadro de texto?
no mostrar autocompletar html (2)
Nuestra aplicación WinForms realiza una carga diferida de los datos para completar automáticamente un cuadro de texto. El pseudocódigo para esto es el siguiente;
- Tipos de usuario en TextBox
- Al escribir la pausa, determina si necesitamos buscar los datos de autocompletar
- En el hilo de trabajo, póngase en contacto con el servidor y obtenga datos
- Invocar de nuevo al hilo de UI
- Establecer
textBox.AutoCompleteCustomSource = fetchedAutoCompleteStringCollection;
- Forzar el cuadro de texto para desplegar su menú desplegable de autocompletar.
Actualmente estoy teniendo problemas con el # 6. Como hackeo, hago lo siguiente para simular una pulsación de tecla que funciona, pero no funciona en todas las situaciones.
// This is a hack, but the only way that I have found to get the autocomplete
// to drop down once the data is returned.
textBox.SelectionStart = textBox.Text.Length;
textBox.SelectionLength = 0;
SendKeys.Send( " {BACKSPACE}" );
Debe haber una mejor manera. No puedo creer que soy la única persona que obtiene datos automáticos completos de forma asincrónica. ¿Cómo debería estar haciendo esto?
EDITAR: Una llamada de Win32 para provocar que el menú desplegable Autocompletar sea aceptable. No me importa invitar a salir si tengo que hacerlo.
He escrito una clase de autocompletar asíncrona para un TextBox usando solo código administrado. Espero eso ayude.
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
namespace TextboxAutocomplete
{
public abstract class AutoCompleteSource
{
private TextBox mTextBox;
private AutoCompleteMode mAutoCompleteMode;
public AutoCompleteSource(TextBox textbox) :
this(textbox, AutoCompleteMode.Suggest) { }
public AutoCompleteSource(TextBox textbox, AutoCompleteMode mode)
{
if (textbox == null)
throw new ArgumentNullException("textbox");
if (textbox.IsDisposed)
throw new ArgumentException("textbox");
mTextBox = textbox;
mAutoCompleteMode = mode;
mTextBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.None;
BackgroundWorker autoCompleteLoader = new BackgroundWorker();
autoCompleteLoader.DoWork += new DoWorkEventHandler(autoCompleteLoader_DoWork);
autoCompleteLoader.RunWorkerCompleted += new RunWorkerCompletedEventHandler(autoCompleteLoader_RunWorkerCompleted);
autoCompleteLoader.RunWorkerAsync();
}
void autoCompleteLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
AutoCompleteStringCollection collection = e.Result as AutoCompleteStringCollection;
if (collection == null) return;
if (mTextBox.InvokeRequired)
{
mTextBox.Invoke(new SetAutocompleteSource(DoSetAutoCompleteSource), new object[] { collection });
}
else
{
DoSetAutoCompleteSource(collection);
}
}
protected void DoSetAutoCompleteSource(AutoCompleteStringCollection collection)
{
if (mTextBox.IsDisposed) return;
mTextBox.AutoCompleteMode = mAutoCompleteMode;
mTextBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.CustomSource;
mTextBox.AutoCompleteCustomSource = collection;
}
void autoCompleteLoader_DoWork(object sender, DoWorkEventArgs e)
{
List<string> autoCompleteItems = GetAutocompleteItems();
if (autoCompleteItems == null) return;
AutoCompleteStringCollection collection = new AutoCompleteStringCollection();
collection.AddRange(GetAutocompleteItems().ToArray());
e.Result = collection;
}
protected abstract List<string> GetAutocompleteItems();
}
internal delegate void SetAutocompleteSource(AutoCompleteStringCollection collection);
}
Implementación de ejemplo:
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;
namespace TextboxAutocomplete
{
class MockAutoCompleteSource : AutoCompleteSource
{
public MockAutoCompleteSource(TextBox textbox)
: base(textbox)
{
}
protected override List<string> GetAutocompleteItems()
{
List<string> result = new List<string>();
for (int i = 0; i < 2500; i++)
{
result.Add(Guid.NewGuid().ToString());
}
return result;
}
}
}
Cómo usarlo:
...
TextBox myTextbox = new TextBox();
MockAutoCompleteSource autoComplete =
new MockAutoCompleteSource(myTextbox);
...
Normalmente, utilizaría la interoperabilidad COM y IAutoComplete
la IAutoComplete
, IAutoComplete2
o IAutoCompleteDropDown
. Lamentablemente, ninguno de estos tiene métodos para obligar a la autocompletar a desplegarse.
Es posible que desee utilizar Spy ++ y ver los mensajes de Windows que se envían al control cuando se muestra automáticamente. Es posible que encuentre un mensaje de comando que lo activará. Por supuesto, este es un detalle de implementación, pero podría ser la única manera de hacerlo aquí.