约束组合框的高度

时间:2014-01-06 19:44:42

标签: c# winforms

我在ToolStripControlHost中的一个面板中有一个组合框,我知道我可能不应该在ToolStrip之外使用ToolStrip相关的类但我找不到任何其他等待使控件覆盖其他控件/窗口。我遇到的问题是,随着更多项目被添加到组合框中,它最终会越来越多地进入屏幕,最终我最终将组合框从屏幕顶部一直向下移动到底部。屏幕。

我希望它能够向下扩展而不是向上扩展,如果它用完了房间,那么它应该滚动。我试图通过将其包装在具有AutoScroll = true的Panel中来实现此目的。每次将项目添加到组合框时,我都会设置面板的高度,如下所示:

var screenY = PointToScreen(_pnlListBoxContainer.Location).Y;
var newBottom = _listBox.Height + screenY;
if (newBottom > Screen.PrimaryScreen.Bounds.Height)
{
    _pnlListBoxContainer.Height = Screen.PrimaryScreen.Bounds.Height - screenY;
}
else
{
    _pnlListBoxContainer.Height = newBottom;
}
_pnlListBoxContainer.MaximumSize = _pnlListBoxContainer.Size;

我对winforms很新,我不确定这是否应该有效,或者是否有更好的方法,目前它不起作用。我做错了什么?

谢谢,

P.S。完整的(非常混乱和被黑客攻击的)代码在这里 - 抱歉:

public class AutoCompleteTextBox : TransparentTextboxWithBorder
{
    private ToolStripDropDown _popupControl;
    private ToolStripControlHost _controlHost;
    private Panel _pnlListBoxContainer;
    private ListBox _listBox;
    private bool _isAdded;
    private IAutoCompletable[] _values;
    private String _formerValue = String.Empty;
    public Font ListBoxFont
    {
        get { return _listBox.Font; }
        set { _listBox.Font = value; }
    }

    public event AutoCompleteTextBoxItemSelectedEventHandler OnItemSelected;

    public void ItemSelected()
    {
        InsertWord((String)_listBox.SelectedItem);
        ResetListBox();
        _formerValue = this.Text;
        if (OnItemSelected != null)
        {
            var item = Values.First(v => v.DisplayText == (string)_listBox.SelectedItem);
            OnItemSelected(this, new AutoCompleteTextBoxItemSelectedEventArgs { SelectedItem = item });
        }
    }

    public AutoCompleteTextBox()
    {
        InitializeComponent();
        ResetListBox();

    }

    private void InitializeComponent()
    {
        _listBox = new ListBox();
        _pnlListBoxContainer = new Panel { BackColor = Color.Red, Width = 100, Height = 400,AutoScroll = true};
        _pnlListBoxContainer.MinimumSize = _pnlListBoxContainer.Size;
        _pnlListBoxContainer.Controls.Add(_listBox);
        _popupControl = new ToolStripDropDown();
        _popupControl.Padding = new Padding(0);
        _popupControl.Margin = new Padding(0);
        _popupControl.AutoClose = false; // Focus bug - http://social.msdn.microsoft.com/Forums/windows/en-US/b8f9cf48-9bd4-4e8e-a9b7-bedc7491c619/toolstripcontrolhost-focus-problem?forum=winforms
        _popupControl.AutoSize = true;
        //_controlHost = new ToolStripControlHost(_listBox);
        _controlHost = new ToolStripControlHost(_pnlListBoxContainer);
        _controlHost.Padding = new Padding(0);
        _controlHost.Margin = new Padding(0);

        _popupControl.Items.Add(_controlHost);
        _listBox.IntegralHeight = true;
        _listBox.MouseDown += _listBox_Click;
        this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.this_KeyDown);
        this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.this_KeyUp);
        this.LostFocus += AutoCompleteTextBox_LostFocus;


        // Fixed by AutoClose = false above
        // List box is now completly seperate so it needs its own key handlers
        //_controlHost.KeyDown +=  new System.Windows.Forms.KeyEventHandler(this.this_KeyDown);
        //_controlHost.KeyUp += (sender, args) =>
        //{
        //    if (args.KeyCode == Keys.Tab)
        //    {
        //        // For some reason the key down event doesnt fire for tab when in a controlhost so we just use key up
        //        this_KeyDown(sender, args);
        //    }
        //    this_KeyUp(sender, args);
        //};

    }

    void AutoCompleteTextBox_LostFocus(object sender, EventArgs e)
    {
        // Firing close means that the selected index changed event doesn't fire so we delay it
        var tmr = new Timer();
        tmr.Interval = 100;
        tmr.Tick += (o, args) =>
        {
            _popupControl.Close();
            tmr.Stop();
        };
        tmr.Start();
    }

    void _listBox_Click(object sender, EventArgs e)
    {
        ItemSelected();
    }

    private void ShowListBox()
    {
        if (!_isAdded)
        {
            //_listBox.Left = this.Left;
            //_listBox.Top = this.Top + this.Height;
            //_pnlListBoxContainer.Left = this.Left;
            //_pnlListBoxContainer.Top = this.Top + this.Height;
            _isAdded = true;
        }
        //_listBox.Visible = true;
        //_listBox.BringToFront();
        _pnlListBoxContainer.Visible = true;
        _pnlListBoxContainer.BringToFront();
        _popupControl.BackColor = Color.Green;
        _popupControl.Show(this, CalculateDropPosition(), ToolStripDropDownDirection.BelowRight);
    }

    private Point CalculateDropPosition()
    {
        Point point = new Point(0, this.Height);
        if ((this.PointToScreen(new Point(0, 0)).Y + this.Height + _controlHost.Height) > Screen.PrimaryScreen.WorkingArea.Height)
        {
            point.Y = -this._controlHost.Height - 7;
        }
        return point;
    }

    public void ResetListBox()
    {
        _popupControl.Close();
    }

    public void Reset()
    {
        ResetListBox();
        _formerValue = string.Empty;
        _oldMatchesHashCode = 0;
    }

    private void this_KeyUp(object sender, KeyEventArgs e)
    {
        UpdateListBox();
    }

    private void this_KeyDown(object sender, KeyEventArgs e)
    {
        switch (e.KeyCode)
        {
            case Keys.Return:
            case Keys.Tab:
                {
                    if (_listBox.Visible)
                    {
                        ItemSelected();
                    }
                    break;
                }
            case Keys.Down:
                {
                    if ((_listBox.Visible) && (_listBox.SelectedIndex < _listBox.Items.Count - 1))
                    {
                        _listBox.SelectedIndex++;
                    }
                    break;
                }
            case Keys.Up:
                {
                    if ((_listBox.Visible) && (_listBox.SelectedIndex > 0))
                    {
                        _listBox.SelectedIndex--;
                    }
                    break;
                }
        }
    }

    protected override bool IsInputKey(Keys keyData)
    {
        switch (keyData)
        {
            case Keys.Tab:
                return true;
            default:
                return base.IsInputKey(keyData);
        }
    }

    private int _oldMatchesHashCode = 0;
    private void UpdateListBox()
    {
        if (this.Text != _formerValue)
        {
            _formerValue = this.Text;
            String word = GetWord();

            if (word.Length > 0)
            {
                var matches = Array.FindAll(_values,
                    x => (x.Match(word) && !SelectedValues.Contains(x.DisplayText)));
                int hashCode = 0;
                foreach (var match in matches)
                {
                    unchecked
                    {
                        hashCode += match.DisplayText.GetHashCode();
                    }
                }
                if (hashCode == _oldMatchesHashCode)
                {
                    return;
                }
                _oldMatchesHashCode = hashCode;
                if (matches.Length > 0)
                {
                    SuspendLayout();
                    ShowListBox();
                    _listBox.Items.Clear();
                    Array.ForEach(matches, x => _listBox.Items.Add(x.DisplayText));
                    _listBox.SelectedIndex = 0;
                    _listBox.Height = 0;
                    _listBox.Width = 0;
                    this.Focus();
                    using (Graphics graphics = _listBox.CreateGraphics())
                    {
                        for (int i = 0; i < _listBox.Items.Count; i++)
                        {
                            _listBox.Height += _listBox.GetItemHeight(i);
                            // it item width is larger than the current one
                            // set it to the new max item width
                            // GetItemRectangle does not work for me
                            // we add a little extra space by using '_'
                            int itemWidth = (int)graphics.MeasureString(((String)_listBox.Items[i]) + "_", _listBox.Font).Width;
                            _listBox.Width = (_listBox.Width < itemWidth) ? itemWidth : _listBox.Width;
                        }
                    }

                    if (_listBox.Width < 200)
                        _listBox.Width = 200;
                    _pnlListBoxContainer.Width = _listBox.Width;

                    var screenY = PointToScreen(_pnlListBoxContainer.Location).Y;
                    var newBottom = _listBox.Height + screenY;
                    if (newBottom > Screen.PrimaryScreen.Bounds.Height)
                    {
                        _pnlListBoxContainer.Height = Screen.PrimaryScreen.Bounds.Height - screenY;
                    }
                    else
                    {
                        _pnlListBoxContainer.Height = newBottom;
                    }
                    _pnlListBoxContainer.MaximumSize = _pnlListBoxContainer.Size;

                    ResumeLayout();
                }
                else
                {
                    ResetListBox();
                }
            }
            else
            {
                ResetListBox();
                _oldMatchesHashCode = 0;
            }
        }
    }

    private String GetWord()
    {
        String text = this.Text;
        int pos = this.SelectionStart;

        int posStart = text.LastIndexOf(';', (pos < 1) ? 0 : pos - 1);
        posStart = (posStart == -1) ? 0 : posStart + 1;
        int posEnd = text.IndexOf(';', pos);
        posEnd = (posEnd == -1) ? text.Length : posEnd;

        int length = ((posEnd - posStart) < 0) ? 0 : posEnd - posStart;

        return text.Substring(posStart, length);
    }

    private void InsertWord(String newTag)
    {
        String text = this.Text;
        int pos = this.SelectionStart;

        int posStart = text.LastIndexOf(';', (pos < 1) ? 0 : pos - 1);
        posStart = (posStart == -1) ? 0 : posStart + 1;
        int posEnd = text.IndexOf(';', pos);

        String firstPart = text.Substring(0, posStart) + newTag;
        String updatedText = firstPart + ((posEnd == -1) ? "" : text.Substring(posEnd, text.Length - posEnd));


        this.Text = updatedText;
        this.SelectionStart = firstPart.Length;
    }

    public IAutoCompletable[] Values
    {
        get
        {
            return _values;
        }
        set
        {
            _values = value;
        }
    }

    public List<String> SelectedValues
    {
        get
        {
            String[] result = Text.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            return new List<String>(result);
        }
    }

}

1 个答案:

答案 0 :(得分:0)

我想我找到了原因:

单击您的组合框,按F4打开属性窗口并将DropDownHeight属性设置为106并将MaxDropDownItems设置为8.这些是组合框的默认值。