我的应用程序中有一个ListBox
,WinForms
我想禁用该列表中的某些项目,例如,如果我右键单击一个项目,它会被禁用,如果我左键单击一个禁用的项目,它应该被启用。我怎样才能做到这一点?非常感谢
问问题
22556 次
3 回答
5
我找到了一个方法。为此,我们必须创建一个自定义 ListBox 控件。:)
使用它,您可以启用或禁用带有项目索引的项目。
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Security;
using System.Runtime.InteropServices;
namespace Netdev.Windows.Forms
{
public class ListBox : System.Windows.Forms.ListBox
{
public event EventHandler<IndexEventArgs> DisabledItemSelected;
protected virtual void OnDisabledItemSelected(object sender, IndexEventArgs e)
{
if (DisabledItemSelected != null)
{
DisabledItemSelected(sender, e);
}
}
public ListBox()
{
DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
disabledIndices = new DisabledIndexCollection(this);
}
private int originalHeight = 0;
private bool fontChanged = false;
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
fontChanged = true;
this.ItemHeight = FontHeight;
this.Height = GetPreferredHeight();
fontChanged = false;
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
if (!fontChanged)
this.originalHeight = this.Height;
}
public void DisableItem(int index)
{
disabledIndices.Add(index);
}
public void EnableItem(int index)
{
disabledIndices.Remove(index);
}
private int GetPreferredHeight()
{
if (!IntegralHeight)
return this.Height;
int currentHeight = this.originalHeight;
int preferredHeight = PreferredHeight;
if (currentHeight < preferredHeight)
{
// Calculate how many items currentheigh can hold.
int number = currentHeight / ItemHeight;
if (number < Items.Count)
{
preferredHeight = number * ItemHeight;
int delta = currentHeight - preferredHeight;
if (ItemHeight / 2 <= delta)
{
preferredHeight += ItemHeight;
}
preferredHeight += (SystemInformation.BorderSize.Height * 4) + 3;
}
else
{
preferredHeight = currentHeight;
}
}
else
preferredHeight = currentHeight;
return preferredHeight;
}
protected override void OnSelectedIndexChanged(EventArgs e)
{
int currentSelectedIndex = SelectedIndex;
List<int> selectedDisabledIndices = new List<int>();
for (int i = 0; i < SelectedIndices.Count; i++)
{
if (disabledIndices.Contains(SelectedIndices[i]))
{
selectedDisabledIndices.Add(SelectedIndices[i]);
SelectedIndices.Remove(SelectedIndices[i]);
}
}
foreach (int index in selectedDisabledIndices)
{
IndexEventArgs args = new IndexEventArgs(index);
OnDisabledItemSelected(this, args);
}
if (currentSelectedIndex == SelectedIndex)
base.OnSelectedIndexChanged(e);
}
protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs e)
{
base.OnDrawItem(e);
if (DesignMode && Items.Count == 0)
{
return;
}
if (e.Index != ListBox.NoMatches)
{
object item = this.Items[e.Index];
if (disabledIndices.Contains(e.Index))
{
e.Graphics.FillRectangle(SystemBrushes.InactiveBorder, e.Bounds);
if (item != null)
{
e.Graphics.DrawString(item.ToString(), e.Font, SystemBrushes.GrayText, e.Bounds);
}
}
else
{
if (SelectionMode == System.Windows.Forms.SelectionMode.None)
{
e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
if (item != null)
{
e.Graphics.DrawString(item.ToString(), e.Font, SystemBrushes.WindowText, e.Bounds);
}
}
else
{
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds);
e.DrawFocusRectangle();
if (item != null)
{
e.Graphics.DrawString(item.ToString(), e.Font, SystemBrushes.HighlightText, e.Bounds);
}
}
else
{
e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
if (item != null)
{
e.Graphics.DrawString(item.ToString(), e.Font, SystemBrushes.WindowText, e.Bounds);
}
}
}
}
}
}
private DisabledIndexCollection disabledIndices;
public DisabledIndexCollection DisabledIndices
{
get { return disabledIndices; }
}
public class DisabledIndexCollection : IList, ICollection, IEnumerable
{
// Fields
private ListBox owner;
private List<int> innerList = new List<int>();
// Methods
public DisabledIndexCollection(ListBox owner)
{
this.owner = owner;
}
public void Add(int index)
{
if (((this.owner != null) && (this.owner.Items != null)) && ((index != -1) && !this.Contains(index)))
{
innerList.Add(index);
this.owner.SetSelected(index, false);
}
}
public void Clear()
{
if (this.owner != null)
{
innerList.Clear();
}
}
public bool Contains(int selectedIndex)
{
return (this.IndexOf(selectedIndex) != -1);
}
public void CopyTo(Array destination, int index)
{
int count = this.Count;
for (int i = 0; i < count; i++)
{
destination.SetValue(this[i], (int)(i + index));
}
}
public IEnumerator GetEnumerator()
{
return new SelectedIndexEnumerator(this);
}
public int IndexOf(int selectedIndex)
{
if ((selectedIndex >= 0) && (selectedIndex < this.owner.Items.Count))
{
for (int index = 0; index < innerList.Count; index++)
{
if (innerList[index] == selectedIndex)
return index;
}
}
return -1;
}
public void Remove(int index)
{
if (((this.owner != null) && (this.owner.Items != null)) && ((index != -1) && this.Contains(index)))
{
innerList.Remove(index);
this.owner.SetSelected(index, false);
}
}
int IList.Add(object value)
{
throw new NotSupportedException("ListBoxSelectedIndexCollectionIsReadOnly");
}
void IList.Clear()
{
throw new NotSupportedException("ListBoxSelectedIndexCollectionIsReadOnly");
}
bool IList.Contains(object selectedIndex)
{
return ((selectedIndex is int) && this.Contains((int)selectedIndex));
}
int IList.IndexOf(object selectedIndex)
{
if (selectedIndex is int)
{
return this.IndexOf((int)selectedIndex);
}
return -1;
}
void IList.Insert(int index, object value)
{
throw new NotSupportedException("ListBoxSelectedIndexCollectionIsReadOnly");
}
void IList.Remove(object value)
{
throw new NotSupportedException("ListBoxSelectedIndexCollectionIsReadOnly");
}
void IList.RemoveAt(int index)
{
throw new NotSupportedException("ListBoxSelectedIndexCollectionIsReadOnly");
}
// Properties
[Browsable(false)]
public int Count
{
get
{
return this.innerList.Count;
}
}
public bool IsReadOnly
{
get
{
return true;
}
}
public int this[int index]
{
get
{
return IndexOf(index);
}
}
bool ICollection.IsSynchronized
{
get
{
return true;
}
}
object ICollection.SyncRoot
{
get
{
return this;
}
}
bool IList.IsFixedSize
{
get
{
return true;
}
}
object IList.this[int index]
{
get
{
return this[index];
}
set
{
throw new NotSupportedException("ListBoxSelectedIndexCollectionIsReadOnly");
}
}
// Nested Types
private class SelectedIndexEnumerator : IEnumerator
{
// Fields
private int current;
private ListBox.DisabledIndexCollection items;
// Methods
public SelectedIndexEnumerator(ListBox.DisabledIndexCollection items)
{
this.items = items;
this.current = -1;
}
bool IEnumerator.MoveNext()
{
if (this.current < (this.items.Count - 1))
{
this.current++;
return true;
}
this.current = this.items.Count;
return false;
}
void IEnumerator.Reset()
{
this.current = -1;
}
// Properties
object IEnumerator.Current
{
get
{
if ((this.current == -1) || (this.current == this.items.Count))
{
throw new InvalidOperationException("ListEnumCurrentOutOfRange");
}
return this.items[this.current];
}
}
}
}
public new void SetSelected(int index, bool value)
{
int num = (this.Items == null) ? 0 : this.Items.Count;
if ((index < 0) || (index >= num))
{
throw new ArgumentOutOfRangeException("index");
}
if (this.SelectionMode == SelectionMode.None)
{
throw new InvalidOperationException("ListBoxInvalidSelectionMode");
}
if (!disabledIndices.Contains(index))
{
if (!value)
{
if (SelectedIndices.Contains(index))
SelectedIndices.Remove(index);
}
else
{
base.SetSelected(index, value);
}
}
// Selected index deoes not change, however we should redraw the disabled item.
else
{
if (!value)
{
// Remove selected item if it is in the list of selected indices.
if (SelectedIndices.Contains(index))
SelectedIndices.Remove(index);
}
}
Invalidate(GetItemRectangle(index));
}
}
public class IndexEventArgs : EventArgs
{
private int index;
public int Index
{
get
{
return index;
}
set
{
index = value ;
}
}
public IndexEventArgs(int index)
{
Index = index;
}
}
}
要使用:
- 将自定义控件添加到您的工具箱并拖动到您的表单上
- 在列表框上使用此方法
listBox1.DisableItem(index); listBox1.EnableItem(index);
- 使用以下链接下载此内容
于 2013-06-14T17:42:52.297 回答
1
如果由于某种原因自定义控件不合适,您可以通过将结果拆分为两个列表框,从“视觉”的角度获得相同的结果。
第一个控件:ListBoxA(活动)。
第二个控件:ListBoxB(非活动)。
将任何活动/可以选择的项目添加到 ListBoxA,将任何需要禁用的项目添加到 ListBoxB。
对于下一部分,请记住标准 ListBox 条目的默认项高度类似于 18px。
取决于控件绘制模式/如果你已经覆盖了这个
您可以让两个控件垂直对齐 - 将第一个控件的高度动态设置为 18px 乘以 ListBoxA 中的项目数
见下面的例子:(https://snag.gy/4GHYiz.jpg)
当然!这仅在您不需要按给定顺序显示禁用的项目时才有帮助。
于 2017-07-28T10:18:13.410 回答
0
ListBox 中没有本机禁用/启用项。但是,您可以做一些技巧。
首先,您需要为具有Enabled
属性的项目定义自己的类。
然后您需要订阅 MouseDown 事件并检查单击了哪个(右或左)按钮。并根据 x,y 位置获取被点击的项目。然后将Enabled
属性设置为 True/False。下面是一些例子:
您的自定义课程
public class Item
{
public Item()
{
// Enabled by default
Enabled = true;
}
public bool Enabled { get; set; }
public string Value { get; set; }
public override string ToString()
{
return Value;
}
}
鼠标按下事件
private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
var item = (Item)listBox1.Items[listBox1.IndexFromPoint(e.X, e.Y)];
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
item.Enabled = false;
}
else
{
item.Enabled = true;
}
}
于 2013-06-13T16:30:37.147 回答