Подкласс поля со списком работает в коде, но не в дизайнере vs2017 - PullRequest
0 голосов
/ 10 марта 2019

У меня есть Visual Studio 2017, создание пользовательских элементов управления, таких как настраиваемое поле со списком, которое расширяет поле со списком, не загружается из панели инструментов дизайнера. Он отлично работает, используя код для генерации настраиваемого поля со списком, добавления его в качестве элемента управления и продолжения ... Стандартное автозаполнение в поле со списком не подходит, поэтому я использовал другой для поиска подстрок и был более гибким в автоматическом предложении / добавить режим.

Если я загружаю другой проект, который делает то же самое, он работает нормально, поэтому я не уверен, в чем проблема для меня. Я пробовал 64/32 бит, переписывал элемент управления десятки раз, очищал и перестраивал, он показывается в наборе инструментов, подтверждаю, что он работает нормально, используя код для сборки и добавления элемента управления.

Почему VS2017 не позволяет мне перетащить его из ящика для инструментов на мою форму, он всегда выдает ошибку: «Не удалось загрузить элемент панели инструментов« SuggestComboBox ». Он будет удален из панели инструментов.

»

Я пробовал многие другие решения для постов, и ни одно из них, похоже, не работает. Как это возможно, решение компилируется, код добавляет элемент управления и работает нормально, но набор инструментов / дизайнер продолжает работать, когда я использую графический интерфейс? Это проблематично, потому что я не могу использовать конструктор, но невозможно понять, что может быть не так.

Есть идеи? <- Я также запустил рабочий пример проекта из Интернета, скопировал файл, который делает то же самое (поле со списком подкласса), в мой проект, и он тоже потерпел неудачу ... это может быть ошибка vs2017 или какой-то шаг, который я пропустил настраиваете это? </p>

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 голосов
/ 16 марта 2019

Спасибо Реза Агаи, ваше предложение, а также то, что я узнал, - это сборки x64 / x86, которые являются проблемой для пользовательских элементов управления.Либо вам нужен отдельный проект для пользовательских элементов управления, соберите их с x86 и загрузите их в свой проект (всегда с использованием 32-битной версии), но, поскольку у меня был тот же проект, и я выбрал x64 для целевого конструктора.

Так каквсе остальное по-прежнему работало нормально, от кода до исполняемого файла, до дизайнерских форм, в которые уже был включен мой управляющий / пользовательский код управления, было почти невозможно выяснить, в чем дело.

Сборка для 32-битной системы и удаление ВСЕГО, а затем повторноекомпиляции.Проблема решена, только несколько часов: S.VS2017.

...