组合框的子类在代码中起作用,但在Designer vs2017中不起作用

时间:2019-03-10 18:43:08

标签: c# visual-studio-2017 windows-forms-designer

我有Visual Studio 2017,创建自定义组合框(如扩展组合框)的自定义控件无法从设计器工具框中加载。使用代码来生成自定义组合框,将其添加为控件,然后继续运行,效果很好...组合框中的默认自动完成功能还不够,因此我使用了另一个来搜索子字符串,并且在自动建议中更加灵活/附加模式。

如果我加载另一个执行相同功能的项目,它将正常工作,因此我不确定问题出在我身上。我已经尝试了64/32位,重新编写了十次控件,清理并重新构建,它显示在工具箱中,并使用代码来构建和添加控件,以确认它工作正常。

为什么VS2017不允许我将其从工具箱拖到我的窗体上,但总是出现错误:“无法加载工具箱项'SuggestComboBox'。它将从工具箱中删除。

我尝试了许多其他帖子解决方案,但似乎都没有用。解决方案如何编译,代码添加控件并可以正常工作,但是当我使用GUI时,工具箱/设计器始终会失败?这是有问题的,因为我不能使用设计器,但是看不到有什么问题。

有什么想法吗? <-我还从互联网上运行了一个工作示例项目,将执行相同操作的文件(子类组合框)复制到了我的项目中,并且它也失败了……这可能是vs2017错误或我错过的某种步骤设置吗?

using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Windows.Forms;

//@note DataItem is a custom class stored in combo box to have key/value pairs
namespace System.Windows.Forms
{
[ToolboxItem(true)]
partial class SuggestComboBox : ComboBox
{
    #region fields and properties

    private readonly ListBox _suggLb = new ListBox { Visible = false, TabStop = false };
    private readonly BindingList<DataItem> _suggBindingList = new BindingList<DataItem>();

    public int SuggestBoxHeight
    {
        get { return _suggLb.Height; }
        set { if (value > 0) _suggLb.Height = value; }
    }
    #endregion

    /// <summary>
    /// ctor
    /// </summary>
    public SuggestComboBox() 
    {
        _suggLb.DataSource = _suggBindingList;
        _suggLb.Click += SuggLbOnClick;

        ParentChanged += OnParentChanged;
    }

    /// <summary>
    /// the magic happens here ;-)
    /// </summary>
    /// <param name="e"></param>
    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);

        if (!Focused) return;

        _suggBindingList.Clear();
        _suggBindingList.RaiseListChangedEvents = false;

        //do a better comparison then just 'starts with'
        List<DataItem> results = new List<DataItem>();
        foreach(object item in Items)
        {
            //data item or regular
            if( item.ToString().ToLower().Contains( Text.Trim().ToLower()))
            {
                results.Add((DataItem)item);
            }                    
        }

        //add to suggestion box (@todo may need data items...)
        foreach (DataItem result in results)
        {
            _suggBindingList.Add(result);
        }

        _suggBindingList.RaiseListChangedEvents = true;
        _suggBindingList.ResetBindings();

        _suggLb.Visible = _suggBindingList.Any();

        if (_suggBindingList.Count == 1 &&
                    _suggBindingList.Single().ToString().Length == Text.Trim().Length)
        {
            Text = _suggBindingList.Single().ToString();
            Select(0, Text.Length);
            _suggLb.Visible = false;
        }

        //handle zindex issue of suggestion box
        this.BringToFront();
        _suggLb.BringToFront();

    }

    #region size and position of suggest box

    /// <summary>
    /// suggest-ListBox is added to parent control
    /// (in ctor parent isn't already assigned)
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnParentChanged(object sender, EventArgs e)
    {
        Parent.Controls.Add(_suggLb);
        Parent.Controls.SetChildIndex(_suggLb, 0);
        _suggLb.Top = Top + Height - 3;
        _suggLb.Left = Left + 3;
        _suggLb.Width = Width - 20;
        _suggLb.Font = new Font("Segoe UI", 9);
    }

    protected override void OnLocationChanged(EventArgs e)
    {
        base.OnLocationChanged(e);
        _suggLb.Top = Top + Height - 3;
        _suggLb.Left = Left + 3;
    }

    protected override void OnSizeChanged(EventArgs e)
    {
        base.OnSizeChanged(e);
        _suggLb.Width = Width - 20;
    }

    #endregion

    #region visibility of suggest box

    protected override void OnLostFocus(EventArgs e)
    {
        // _suggLb can only getting focused by clicking (because TabStop is off)
        // --> click-eventhandler 'SuggLbOnClick' is called
        if (!_suggLb.Focused)
            HideSuggBox();
        base.OnLostFocus(e);
    }

    private void SuggLbOnClick(object sender, EventArgs eventArgs)
    {
        Text = _suggLb.Text;
        Focus();
    }

    private void HideSuggBox()
    {
        _suggLb.Visible = false;
    }

    protected override void OnDropDown(EventArgs e)
    {
        HideSuggBox();
        base.OnDropDown(e);
    }

    #endregion

    #region keystroke events

    /// <summary>
    /// if the suggest-ListBox is visible some keystrokes
    /// should behave in a custom way
    /// </summary>
    /// <param name="e"></param>
    protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
    {
        if (!_suggLb.Visible)
        {
            base.OnPreviewKeyDown(e);
            return;
        }

        switch (e.KeyCode)
        {
            case Keys.Down:
                if (_suggLb.SelectedIndex < _suggBindingList.Count - 1)
                    _suggLb.SelectedIndex++;
                return;
            case Keys.Up:
                if (_suggLb.SelectedIndex > 0)
                    _suggLb.SelectedIndex--;
                return;
            case Keys.Enter:
                Text = _suggLb.Text;
                Select(0, Text.Length);
                _suggLb.Visible = false;
                return;
            case Keys.Escape:
                HideSuggBox();
                return;
        }

        base.OnPreviewKeyDown(e);
    }

    private static readonly Keys[] KeysToHandle = new[] { Keys.Down, Keys.Up, Keys.Enter, Keys.Escape };
    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        // the keysstrokes of our interest should not be processed be base class:
        if (_suggLb.Visible && KeysToHandle.Contains(keyData))
            return true;
        return base.ProcessCmdKey(ref msg, keyData);
    }
    #endregion
}
}

1 个答案:

答案 0 :(得分:0)

感谢Reza Aghaei,您的建议以及我所学到的x64 / x86版本也是用户控件的问题。您要么为用户控件需要一个单独的项目,然后使用x86进行构建并将它们加载到您的项目中(始终使用32位),但是由于我的项目是同一个项目,而x64却使设计人员陷入了困境。

由于从代码,可执行文件到已经包含我的控件/用户控件代码的设计器表单,其他所有一切仍然运行良好,因此几乎不可能找出问题所在。

构建32位并删除所有内容,然后重新编译。问题解决了,只花了几个小时:S。 VS2017。