我已经看到了一些与此类似的问题,但它们似乎适用于WPF(我不熟悉,并且该解决方案似乎不适用于我)。我有一个OwnerDrawFixed列表框(实际上是2个),如果添加的项目是""
,我用它来绘制水平分隔符项目。我想要的是在点击时完全跳过这些(我点击拖动项目选择它时遇到麻烦)或通过上/下箭头键选择。这是我的DrawItem
事件:
private void ListBox_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index < 0)
return;
e.DrawBackground();
e.Graphics.DrawString((sender as ListBox).Items[e.Index].ToString(), (sender as ListBox).Font, new SolidBrush(e.ForeColor), e.Bounds);
//Draw as a separator if there is no text
if (string.IsNullOrWhiteSpace((sender as ListBox).Items[e.Index].ToString()))
{
e.Graphics.DrawLine(new Pen(Brushes.DarkGray), new Point(e.Bounds.X + 5, e.Bounds.Y + 7), new Point(e.Bounds.X + e.Bounds.Width - 5, e.Bounds.Y + 7));
}
//Doesn't appear to do anything e.DrawBackground isn't..?
//e.DrawFocusRectangle();
}
我尝试过MouseUp,MouseDown和SelectedIndexChanged事件的组合,要么完全清除选择(出于显而易见的原因不适合箭头导航),要么存储先前选择的索引,确定方向,并选择下一个值(如果项目不靠近,有时点击不直观)
我也尝试了myListBox.SelectionMode = SelectionMode.None;
,但出于某种原因(可能是我的绘制事件?)它只是突出显示我选择的每个项目(没有取消选择它们)。
如果我试图禁止选择项目为空字符串的项目,我是否遗漏了某些内容?
答案 0 :(得分:1)
这是一个适合我的简单解决方案。我刚刚将这一事件添加到您发布的代码中:
int lastIndex = 0;
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string s = listBox1.SelectedItem.ToString();
int newIndex = listBox1.SelectedIndex;
if (s == "" )
{
if (newIndex > lastIndex && newIndex < listBox1.Items.Count)
{
listBox1.SelectedIndex++;
}
else if (newIndex < lastIndex && newIndex > 0)
{
listBox1.SelectedIndex--;
}
}
else lastIndex = newIndex;
}
答案 1 :(得分:0)
我修改了ListBox with Disableable Items中的代码以满足您的需求:
public class ListBoxEx : ListBox {
private const int WM_MOUSEMOVE = 0x200;
private const int WM_LBUTTONDOWN = 0x201;
private const int WM_KEYDOWN = 0x100;
private const int VK_LEFT = 0x25;
private const int VK_UP = 0x26;
private const int VK_RIGHT = 0x27;
private const int VK_DOWN = 0x28;
protected override void WndProc(ref Message m) {
// Get params as int
int lParam = m.LParam.ToInt32();
int wParam = m.WParam.ToInt32();
// Intercept mouse selection
if (m.Msg == WM_MOUSEMOVE || m.Msg == WM_LBUTTONDOWN) {
Point clickedPt = new Point();
clickedPt.X = lParam & 0x0000FFFF;
clickedPt.Y = lParam >> 16;
// If point is on a disabled item, ignore mouse
for (int i = 0; i < Items.Count; i++)
if (string.IsNullOrWhiteSpace(Items[i].ToString()) &&
GetItemRectangle(i).Contains(clickedPt))
return;
}
// Intercept keyboard selection
if (m.Msg == WM_KEYDOWN)
if (wParam == VK_DOWN || wParam == VK_RIGHT) {
// Select next enabled item
for (int i = SelectedIndex + 1; i < Items.Count; i++)
if (!string.IsNullOrWhiteSpace(Items[i].ToString())) {
SelectedIndex = i;
break;
}
return;
} else if (wParam == VK_UP || wParam == VK_LEFT) {
// Select previous enabled item
for (int i = SelectedIndex - 1; i >= 0; i--)
if (!string.IsNullOrWhiteSpace(Items[i].ToString())) {
{
SelectedIndex = i;
break;
}
}
return;
}
base.WndProc(ref m);
}
protected override void OnDrawItem(DrawItemEventArgs e) {
if (e.Index > -1) {
string item = this.Items[e.Index].ToString();
if (string.IsNullOrWhiteSpace(item)) {
e.Graphics.DrawLine(Pens.DarkGray, new Point(e.Bounds.X + 5, e.Bounds.Y + 7),
new Point(e.Bounds.Right - 5, e.Bounds.Y + 7));
} else {
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) {
e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds);
TextRenderer.DrawText(e.Graphics, item, e.Font, e.Bounds, SystemColors.HighlightText);
} else {
e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
TextRenderer.DrawText(e.Graphics, item, e.Font, e.Bounds, SystemColors.WindowText);
}
}
}
base.OnDrawItem(e);
}
}