7

I have custom ComboBox, where DropDownStyle = ComboBoxStyle.DropDown;.DropDown style is set because I want to set the Text property of the ComboBox to something outside the list of values. Everything works good, except that ComboBox is highlighting the text when it's left and when I click on the combobox editing is avaible. How can I cope with this? To illustrate:

enter image description here

First Picture is where everything looks good, second is the highlight situation, third editing is on.

ContentPenalty
  • 447
  • 1
  • 5
  • 14
  • Could it be that you still have focus on the combo-box? Did you try clicking on other controls and verifying it still does the highlighting. If the combo box has the focus, then highlighting will be there. Or are you trying to disable editing? – haku Sep 17 '14 at 22:27
  • Yes, combo-box still have the focus, when the OnLeave event occur, then the highlighting dissapears. But it should dissapear when the dropdown is hided. – ContentPenalty Sep 17 '14 at 22:45
  • It is just a screenshot, doesn't help us help you. There's a bug in the code that nobody can see. You can diagnose it by overriding OnHandleCreated() and setting a breakpoint on it. Second time it fires you'll get the Wall of Blue. The call stack tells the tale. – Hans Passant Sep 17 '14 at 23:39

8 Answers8

11

Try un-selecting the text after the DropDown closes:

void comboBox1_DropDownClosed(object sender, EventArgs e) {
  this.BeginInvoke(new Action(() => { comboBox1.Select(0, 0); }));
}
LarsTech
  • 80,625
  • 14
  • 153
  • 225
  • Yes, thank you, I had not thought about it. This eliminated highlighting when dropdown is hidden. The editable problem is still here. – ContentPenalty Sep 17 '14 at 23:01
  • @user1816806 Not sure I know what the "editable problem" is. Can you expand on that? – LarsTech Sep 17 '14 at 23:03
  • When I click on the combobox, the vertical editing line shows as on the third presented picture. I cant remove or edit the text, because I blocked it in the custom combobox logic, but the line is still present. – ContentPenalty Sep 17 '14 at 23:08
  • 1
    @user1816806 You want to hide the caret in the TextBox? I'm guessing you would have to find the TextBox handle inside the ComboBox control and pinvoke the HideCaret function. If the end user can type inside the box, they need to see the Caret. Don't hide it from them. – LarsTech Sep 17 '14 at 23:14
  • @LarsTech Do you know why it doesn't work when comboBox1.Select(0, 0); is put by itself without BeginInvoke? Basically that's code handling the selection, isn't it? Thanks. – haku Sep 17 '14 at 23:23
  • Yes, exactly I want to hide the caret. Getting the TextBox handle might be complicated,but I will try to do it this way.Thanks a lot. – ContentPenalty Sep 17 '14 at 23:25
  • 1
    @HakuKalay The code that highlights the text comes after the DropDownClosed event happens, so the selection gets reset to the full highlight. BeginInvoke is a way of running your code after the event, so then it undoes that action. – LarsTech Sep 18 '14 at 01:25
  • @LarsTech You mentioned in a previous comment that to hide the Caret one would need to get the TextBox handle inside the ComboBox control. Any chance you would know how to get that? I can use HideCaret on a normal TextBox and it works. But using it on a ComboBox does nothing and I'm not sure how to get the TextBox handle from a ComboBox like you suggested? – Calcolat Aug 06 '15 at 17:26
  • 1
    @Calcolat See if this answer helps you: [Use of NativeWindow for ComboBox causes exception in Dispose-method](http://stackoverflow.com/a/12977295/719186) – LarsTech Aug 06 '15 at 17:47
  • 1
    @LarsTech That's awesome. Using your SendMessageCb example I could get the textbox handle, as well as the other combobox handles, which was cool. Thanks for taking the time to respond to a comment on an old question. I can't accept this as an answer, so I've gone ahead and upvoted both your answers instead. Thanks! – Calcolat Aug 07 '15 at 06:34
4

If you are referring to disabling the highlighting and editing, then you might want to consider setting the DropdownStyle property to DropdownList.

yourComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
haku
  • 4,105
  • 7
  • 38
  • 63
  • I know about the `DropdownList` but it casues another problem, that I mentioned "set the Text property of the ComboBox to something outside the list of values" – ContentPenalty Sep 17 '14 at 22:46
4

Tricky problem to solve. It seems to be from the Resize event. There are a lot of solutions that do something similar to this, but none that I've seen worked for me until I tried this. (This is a solution that does not require inheritance from ComboBox; inheriting is probably a much more straight forward solution, but requires you to always use your inherited class and never the actual ComboBox class.)

comboBox.Resize += (s, e) => {
   if (!comboBox.IsHandleCreated)
      return;  // avoid possible exception

   comboBox.BeginInvoke(new Action(() => comboBox.SelectionLength = 0));
};

Set the selection length to zero to get rid of the highlight, but when? Other examples do it in other places, but the problem seems to be specifically caused by Resize, so doing it after Resize fixes it consistently, at least for me. (Can still see it flicker when you resize the window though, but it always ends up ok.)

BeginInvoke ensures that it happens sufficiently after Resize to work, and the check for IsHandleCreated prevents it from being called before the handle is created, in which case BeginInvoke would throw an exception.

This slightly more complex version includes some checks to prevent a focused control from losing highlight, since it actually should have it. It also doesn't fire if the parent doesn't exist yet, or if the parent does not have an active control yet, both signs that things are too early.

comboBox.Resize += (s, e) => {
   if (!comboBox.IsHandleCreated)
      return;

   comboBox.BeginInvoke(new Action(() => {
      var parent = comboBox.FindForm();
      if (parent == null)
         return;

      if (parent.ActiveControl == null)
         return;

      if (parent.ActiveControl == comboBox)
         return;

      comboBox.SelectionLength = 0;
   }));
};

I tried to make a version that would 'preserve' the selection length rather than always set it to zero, but I couldn't get it to synchronize properly. Many Resize events can fire before the BeginInvoke delegates start to fire, so the preserved value will always be overwritten by the broken one. I tried saving them all in a Queue or Stack, but in both cases, I was unable to reverse the ordering (not really sure why, since that makes no sense).

Dave Cousineau
  • 12,154
  • 8
  • 64
  • 80
3

To solve the same I have tried almost EVERYTHING:

  • setting the DropdownStyle property to DropdownList
  • this.BeginInvoke(new Action(() => { comboBox1.Select(0, 0); }));
  • combobox1.SelectionLength = 0;
  • changing comboBox.TabIndex
  • Not tried SendKeys.Send("{ESC}"); because it is not a reliable solution

Nothing helped. The only stable and working solution was to move a focus on another Label control:

    label.Focus();

You could also hide that label.

Irshad
  • 3,071
  • 5
  • 30
  • 51
Vadim K.
  • 331
  • 3
  • 9
1

I know this post is old but recently I have the same problem with combobox.

Situation : I have an editable combobox which propose complete words when user write some letters.

But when I want to type a letter, combobox auto highlight the text and the next letter auto replace the previous.

Solution : I use a textbox to avoid any highlight like that:

<ComboBox IsTextSearchEnabled="False" IsEditable="True" x:Name="CMB_ClientName"/>
<TextBox Text="{Binding ElementName=CMB_ClientName, Path=Text}" TextChanged="ComboBoxChange" x:Name="TXT_ClientName"/>

And I generate the textbox TextChanged event :

private void ComboBoxChange(object sender, TextChangedEventArgs e)
    {
        //Clear ComboBox items
        CMB_ClientName.Items.Clear();
        //Auto Open DropDownList
        CMB_ClientName.IsDropDownOpen = true;

        //Get data from database (use entity framework 6.x)
        dbEntity.Client.Load();

        //Attribute Data to variable
        var clients = dbEntity.Client.Local;


        foreach (Client client in clients)
        {
            //If data begin with the texbox text, the data is add to the combobox items list.
            if (client.Nom.ToLower().StartsWith(TXT_NomClient.Text.ToLower()))
            {
                CMB_ClientName.Items.Add(client.Nom);
            }
        }
    }

I know this solution isn't realy beautifull, but it is for me the easiest solution to avoid highlight text and all the solutions in this post don't work for me.

I hope this solution will be helpfull, thanks for reading.

Math.

Ps: My apologies, my English is not very good. I hope you will understand me correctly.

1

Nothing worked for me ( I want the form to load with no highlighting in any combobox) until I set the combobox property TabStop to false. This meant that one of my buttons took the tab highlight which I didn't like so I set them all to false for start up and adjusted them programatically as needed.

jvl
  • 11
  • 1
0

I know this is an old thread, but my solution is similar to that of the others, but relies on the Form.ResizeEnd event. In its event handler, I iterate through the ComboBoxes and set ComboBox.SelectionLength to 0.

private void Form_ResizeEnd(object sender, EventArgs e)
{
    foreach(ComboBox comboBox in parentControl.Controls.OfType<ComboBox>
    {
        comboBox.SelectionLength = 0;
    }
}
peter
  • 11
  • 1
0

This is what worked for me:

  1. Set DrawMode to OwnerDrawFixed

  2. Set cbxSubsystems.DrawItem event to the function below

private void cbxSubsystems_DrawItem(object sender, DrawItemEventArgs e)
{
    Color BgClr;
    Color TxClr;

    if( (e.State & DrawItemState.ComboBoxEdit) == DrawItemState.ComboBoxEdit )
    {
        // Do not highlight main display
        BgClr = cbxSubsystems.BackColor;
        TxClr = cbxSubsystems.ForeColor;
    }
    else
    {
        BgClr = e.BackColor;
        TxClr = e.ForeColor;
    }

    e.Graphics.FillRectangle(new SolidBrush(BgClr), e.Bounds);

    TextRenderer.DrawText(e.Graphics, cbxSubsystems.Items[e.Index].ToString(), e.Font, e.Bounds,
        TxClr, BgClr, TextFormatFlags.Left | TextFormatFlags.VerticalCenter );
}

Jorsh
  • 1