【问题标题】:Editbox portion of ComboBox gets selected automatically组合框的编辑框部分被自动选中
【发布时间】:2010-10-21 15:06:55
【问题描述】:

我有一个小问题困扰了我几个小时。

在我的 WinForms (.NET 3.5) 应用程序中,我在运行时在 TableLayoutPanel 中创建了一些 ComboBoxes (DropDownStyle = DropDown) 并用字符串填充它。组合框配置为自动调整大小(锚点 = 左 | 右)。

问题在于,无论何时调整组合框的大小(即调整对话框的大小),组合框的编辑框部分都会被完全选中/突出显示。在我看来,这会给客户造成非常混乱的影响,我想避免这种影响。

如果 ComboBox 具有固定大小,则不会出现此问题。

另请注意,更改 DropDownStyle 不是一个选项 - 我需要手动输入文本的可能性。

我已经尝试过重写 OnPaint 方法,但效果不佳。 我还尝试清除 ComboBox.Resize 事件中的选择,这在某种程度上起作用,但似乎是一个非常丑陋的解决方案 - 有很多闪烁,故意选择的文本被取消选择,我必须将事件处理程序添加到每个以及我对话框中的每个 ComboBox。

这个问题有更好的解决方案吗?

提前谢谢你。

问候, 安迪

【问题讨论】:

  • 使用 DropDownList 时,文本部分不可编辑。你是说 DropDown 吗?

标签: c# .net winforms combobox


【解决方案1】:

这是一个老问题,但我发现它正在寻找答案并最终实现了我自己的解决方案。还是贴在这里吧?

    foreach (var cb in Controls.OfType<ComboBox>())
    {
        cb.Resize += (sender, e) => {
            if (!cb.Focused)
                cb.SelectionLength = 0;
        };
    }

故意选择的文本被取消选择

此 WinForms 错误不会影响选定的组合框,因此通过忽略具有焦点的组合框,我们可以解决丢失当前选择的问题。

我必须添加事件处理程序 到我的每一个 ComboBox 对话框。

由 foreach 循环处理。如果您不想破坏设计器,或者让设计器破坏它,请将其放在 InitializeComponent() 或您的 .ctor 中。

有很多闪烁

如果我快速调整大小,我只会看到闪烁,但我在 Win7 上,所以在 XP 上可能会有所不同。

【讨论】:

  • 我想建议做一个 this.SelectNextControl 或一个 combobox.SelectNextControl
  • 谢谢。它一直困扰着我一段时间,直到现在才开始修复它。我的应用程序中的每个组合框类型控件都继承自基础对象(因此我可以拥有标签、常用方法等)。为组合框添加 OnResize 事件处理程序已经解决了我的问题,而不必进行迭代。谢谢!
【解决方案2】:

这似乎是ComboBoxDropDownStyleDropDown 的本机Windows 实现中的一个错误。

此处其他答案中详述的修复(在ComboBoxResize 事件中将SelectionLength 属性设置为0(零))在大多数情况下都能正常工作。

但是,我发现即使是解决此错误的修复程序也并不总是有效。如果ComboBoxTableLayoutPanel 中,并且如果TableLayoutPanel 有不止一列具有Percent 大小类型,则该修复通常不起作用。

一张图片胜过一千个字。请参阅以下我为演示问题而制作的表单的屏幕截图。

【讨论】:

  • 我可以通过使用 TableLayoutPanel Resize 事件来解决这个问题。 foreach (ComboBox cbo in tableLayoutPanel1.Controls.OfType&lt;ComboBox&gt;()) tableLayoutPanel1.Resize += (s, e) =&gt; { if (!cbo.Focused) cbo.SelectionLength = 0; };
【解决方案3】:

哇。谢谢各位!

显然这个错误已经存在很多年了。 我正在使用 .Net 4 (Visual Studio 2010) 构建用户控件。 这是我对 bsneeze 的代码稍作修改的版本。

干杯

using System.Windows.Forms;
using System.Linq;

public MyUserControlCtor()
{
    InitializeComponent();

    foreach( Control ctrl in Controls)
    {
        ComboBox cb = ctrl as ComboBox;
        if (cb != null)
        {
            cb.Resize += (sender, e) =>
            {
                if (!cb.Focused)
                    this.FCHZ_ComboBox.SelectionLength = 0;
            };
        }
    } 
}

【讨论】:

  • 我更喜欢这种表示法 foreach (var cb in Controls.OfType())
【解决方案4】:

到目前为止,没有一个答案对我有用。我发现的唯一可靠方法是通过BeginInvoke 异步发布消息,在控件上的所有其他活动完成后将SelectionLength 设置为零。闪烁的数量非常烦人且不专业,但这是我能想到的最好的......到目前为止。

internal class FixedComboBox : ComboBox
{
    protected override void OnResize(EventArgs e)
    {
        if (IsHandleCreated && !Focused)
        {
            BeginInvoke((Action)(() =>
                {
                    SelectionLength = 0;
                }));
        }
        base.OnResize(e);
    }
}

【讨论】:

  • 我想知道这里的其他答案是否对您不起作用,因为您的 ComboBoxTableLayoutPanel 中?
  • @JeffRoe:我不记得细节了。这是很久以前的事了,但是是的,这是很有可能的。
【解决方案5】:

WM_WINDOWPOSCHANGED 被调用时,我将 selectionLength 更改为 0。 即使 tableLayoutPanel 设置为 % 也可以工作。

protected override void WndProc(ref Message m) {
    base.WndProc(ref m);

    if(m.Msg == 0x0047) {   // WM_WINDOWPOSCHANGED = 0x0047 
        if (SelectionLength != 0) {
            SelectionLength = 0;
        }
    }
}

【讨论】:

    【解决方案6】:

    我发现在组合框所在的任何控件的调整大小事件上将组合框的选择长度设置为 0 会导致 很多 更少的闪烁,而不是在调整组合本身。

    我实际上在 VB.Net 中实现了这一点,但它应该同样适用于 C#。

    【讨论】:

      【解决方案7】:

      为 ComboBox 的父容器处理 Resize 事件。把这一行放在那里:

      MyComboBox.SelectionLength = 0

      一个例子(显然是 VB):

      Private Sub MyControl_Resize(sender As Object, e As EventArgs) Handles Me.Resize
      
          MyComboBox.SelectionLength = 0
      
      End Sub
      

      祝你好运!

      --BP

      【讨论】:

        【解决方案8】:

        对于 TableLayoutPanel 中的 ComboBox,在 ComboBox.Resize 事件上设置 .SelectionLength = 0 不起作用,但在 TableLayoutPanel.Resize 事件上这样做:

        Private Sub TableLayoutPanel_Resize(sender As Object, e As EventArgs)
            Dim curr_panel = TryCast(sender, System.Windows.Forms.TableLayoutPanel)
            For Each curr_combo As ComboBox In curr_panel.Controls.OfType(Of ComboBox)
                If ((Not curr_combo.Focused) And curr_combo.DropDownStyle = ComboBoxStyle.DropDown) Then
                        curr_combo.SelectionLength = 0
                End If
            Next
        End Sub
        
        
        dim panel as new TableLayoutPanel with {
            ...
        }
        AddHandler panel.Resize, AddressOf TableLayoutPanel_Resize
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-09
          • 1970-01-01
          • 2015-01-13
          • 1970-01-01
          • 2014-06-18
          • 2012-04-17
          相关资源
          最近更新 更多