2

I have a WinForms ComboBox within an Outlook Add-in which populates the drop-down with user names, when the user types names in the edit box. When the user reaches the third character. The data source of the ComboBox is assigned at this point, and the curser jumps to the beginning of the edit box instead of staying at the end.

The behavior I want is that the cursor stays at the end of the string I am typing, even when the drop-down is populated with more data.

I've tried hacking this with send keys, but it doesn't always work. The code which reads the keys below is in the key pressed event.

private void comboBox1_KeyPress(object sender, KeyEventArgs e)
{
    var acceptableKeys = ConfigurationManager.AppSettings["AcceptableKeys"];
    if (cmbAssignedTo.Text.Length > 2 && acceptableKeys.Contains(e.KeyCode.ToString().ToUpper()) && e.Modifiers == Keys.None)
    {
        var request = RestHandler.CreateRequest(ConfigurationManager.AppSettings["ContactsSearchResource"] + cmbAssignedTo.Text.Trim(), Method.GET);

        var response = RestHandler.ExecuteRequest(request, ConfigurationManager.AppSettings["myServiceURL"]);
        this.cmbAssignedTo.DataSourceChanged -= new System.EventHandler(this.cmbAssignedTo_DataSourceChanged); 
        //Assign a new data source
        DataHandler.UpdateComboboxDataSource(cmbAssignedTo, response.Content);
        this.cmbAssignedTo.DataSourceChanged += new System.EventHandler(this.cmbAssignedTo_DataSourceChanged);

    }
    e.Handled = true;
}

Edit

internal static void UpdateComboboxDataSource(ComboBox cmbAssignedTo, string data)
    {
      var list = BuildAssignmentList(data);
      if ((list.Count() == 0 && cmbAssignedTo.Items.Count == 0) || list.Count() > 0)
      {
            var savedText = cmbAssignedTo.Text;
            cmbAssignedTo.DataSource = list;
            cmbAssignedTo.SelectedValue = "";
            cmbAssignedTo.Text = savedText;
            SendKeys.Send("{end}");
        }
        if (cmbAssignedTo.Items.Count > 0)
        {
            cmbAssignedTo.DroppedDown = true;
            Cursor.Current = Cursors.Default;
        }
    }

I don't see how I can update the dropdown without changing the DataSource and that change appears to cause the cursor to jump. Should I try different event than KeyPressed? Is there some other solution I'm missing?

Blanthor
  • 2,568
  • 8
  • 48
  • 66
  • Add code of the `cmbAssignedTo_DataSourceChanged` to the question please – Samvel Petrosov May 25 '17 at 17:43
  • Added the code where the DataSource is actually changed. The event method @S.Petrosov requests is actually a no-op. I will remove that from the KeyPressed event. – Blanthor May 25 '17 at 18:13
  • 1
    Try this validation delay trick I found: https://stackoverflow.com/questions/8001450/c-sharp-wait-for-user-to-finish-typing-in-a-text-box Regards, Tim – Tim May 25 '17 at 18:23

1 Answers1

0

As another hack you can play with ComboBox's SelectionStart property:

int i = comboBox1.SelectionStart;
comboBox1.DataSource = new System.Collections.Generic.List<string>(){"aaaaaa", "bbbbbb", "ccccccc"};
comboBox1.SelectionStart = i;

This code changes the DataSource and retain the cursor position. If you want cursor to be always at end - set SelectionStart to comboBox1.Text.Length.

UPD: To fight against the "first item selection" you may use another hack:

private bool cbLock = false;

private void comboBox1_TextChanged(object sender, EventArgs e)
{
  // lock is required, as this event also will occur when changing the selected index
  if (cbLock)
    return;

  cbLock = true;
  int i = comboBox1.SelectionStart;

  // store the typed string before changing DS
  string text = comboBox1.Text.Substring(0, i);

  List<string> ds = new System.Collections.Generic.List<string>() { "aaaaaa", "aaabbb", "aaacccc" };
  comboBox1.DataSource = ds;

  // select first match manually
  for (int index = 0; index < ds.Count; index++)
  {
    string s = ds[index];
    if (s.StartsWith(text))
    {
      comboBox1.SelectedIndex = index;
      break;
    }
  }

  // restore cursor position and free the lock
  comboBox1.SelectionStart = i;
  cbLock = false;
}

When typing "aaab" it selects the "aaabbb" string.

rattler
  • 379
  • 2
  • 5
  • 15
  • This is close, but it moves all the way to the end of the first choice in autocomplete. The other selections that match the first four characters are ignored. For instance if I get Mike A and Mike B in the drop-down, it automatically selects Mike A. But I want to be able to chose Mike B. – Blanthor May 25 '17 at 18:18