65.9K
CodeProject 正在变化。 阅读更多。
Home

具有启用/禁用项目功能的自定义列表框控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.44/5 (7投票s)

2010年6月1日

CPOL

2分钟阅读

viewsIcon

55119

downloadIcon

1308

具有启用/禁用项目功能的 C# 自定义 Listbox 控件

引言

我曾经遇到过一个案例,需要在 System.Windows.Forms.ListBox 控件中显示一些最终用户无法选择的项目,但仍然需要显示它们,因为最终用户期望看到它们。问题是 System.Windows.Forms.ListBox 不提供此功能,所以我决定创建自己的用户控件并分享它。

运行时控件

以下是控件在运行时的一些快照:[您可以下载示例项目并运行它].

Image1.JPG

禁用 Item3 [索引为 2] 后,我们将得到

Image2.JPG

现在 Item3 无法被选中,我们将对 Item5 [索引 4] 执行相同的操作,得到

Image3.JPG

启用 Item3 [索引 2] 将使该项目恢复到其默认状态

Image4.JPG

Using the Code

使用此控件非常简单。它的使用方式与内置的 ListBox 控件相同。

private Netdev.Windows.Forms.ListBox listBox1; 
// Create a listbox object.
this.listBox1 = new Netdev.Windows.Forms.ListBox(); 
// Disable the item at the integer location index.
listBox1.DisableItem(index); 
// Enable the item at the integer location index.
listBox1.EnableItem(index); 
// We can also wire an event handler for Disabled items selection event.
// Whenever an end user tries to select a disabled item this event will be fired
this.listBox1.DisabledItemSelected += new System.EventHandler
	<Netdev.Windows.Forms.IndexEventArgs>(this.listBox1_DisabledItemSelected);

代码描述

自定义的核心发生在 OnDrawItem 方法重写中。但是,只有当 DrawMode = DrawMode.OwnerDrawFixed; (控件创建时的默认属性值)以及禁用的索引 [项目] 列表时,运行时才会调用此方法,如这个构造函数所示。

public ListBox()
{
      DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
      disabledIndices = new DisabledIndexCollection(this);
}    

DisabledIndexCollection:这是一个自定义集合,与保存 SelectedIndices 属性的集合相同。此集合跟踪列表中当前禁用的索引,这有助于 OnDrawItem 方法重写将这些项目显示为灰色项目,并防止最终用户选择它们。

以下是 OnDrawItem 方法的代码

protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs e)
{
    base.OnDrawItem(e);
    if (DesignMode  && Items.Count == 0)
    {
        if (e.Index == 0)
        {
            // Draw Control name as an item is design mode.
            e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
            e.Graphics.DrawString(this.Name, e.Font, SystemBrushes.WindowText, e.Bounds);
        }
        return;
    }

    if (e.Index != ListBox.NoMatches)
    {
        object item = this.Items[e.Index];
        // Get the text to display, this depends if the list is bound to data and 
        // DisplayMember, EnableFormating and FormatString are set.
        string displayValue = GetItemText(item);
        
        if (disabledIndices.Contains(e.Index))
        {
            e.Graphics.FillRectangle(SystemBrushes.InactiveBorder, e.Bounds);
            e.Graphics.DrawString(displayValue, e.Font, SystemBrushes.GrayText, e.Bounds);
        }
        else
        {
            if (SelectionMode == System.Windows.Forms.SelectionMode.None)
            {
                e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
                e.Graphics.DrawString(displayValue, e.Font, 
			SystemBrushes.WindowText, e.Bounds);
            }
            else
            {
                if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
                {
                    e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds);
                    e.DrawFocusRectangle();
                    e.Graphics.DrawString(displayValue, e.Font, 
			SystemBrushes.HighlightText, e.Bounds);
                }
                else
                {
                    e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
                    e.Graphics.DrawString(displayValue, e.Font, 
			SystemBrushes.WindowText, e.Bounds);
                }
            }
        }
    }
}   

如果某个项目包含在 DisabledIndices 集合中,则将其显示为灰色。

最后,确保拦截 SelectedIndexChanged 事件,如果选定的项目被灰化,则通过重写 OnSelectedIndexChanged 方法来忽略它。

 protected override void OnSelectedIndexChanged(EventArgs e)
{
    // Retrieve new value of selected index.
    int currentSelectedIndex = SelectedIndex;
    List<int> selectedDisabledIndices = new List<int>();

    for (int i = 0; i < SelectedIndices.Count; i++)
    {
        // unselect items that are already disabled.
        if (disabledIndices.Contains(SelectedIndices[i]))
        {
            selectedDisabledIndices.Add(SelectedIndices[i]);
            SelectedIndices.Remove(SelectedIndices[i]);
        }
    }
    foreach (int index in selectedDisabledIndices)
    {
        // Fire DisabledItemSelected event for each 
        // disabled item that has been selected.
        IndexEventArgs args = new IndexEventArgs(index);
        OnDisabledItemSelected(this, args);
    }
    // if updated selected index is different than the 
    // original one then bubble up the event
    if (currentSelectedIndex == SelectedIndex)
        base.OnSelectedIndexChanged(e);
}	 

历史

  • 更新版本 - 修复了与列表绑定到数据时项目显示值相关的问题,或者设置了 DisplayMemberEnableFormating FormatString 时的问题
© . All rights reserved.