我在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);
}
}
}
答案 0 :(得分:0)
我想我找到了原因:
单击您的组合框,按F4打开属性窗口并将DropDownHeight
属性设置为106并将MaxDropDownItems
设置为8.这些是组合框的默认值。