How To Disable Selected Item In List Box

2019-02-17 21:53发布

问题:

I have a ListBox in my WinForms application and I want to disable some items on that list, for example if I right click on an item , it gets disabled and if I left click on a disabled item it should be enabled. How can I do this? Thanks very much

回答1:

I found a way. We must create a custom ListBox Control to do this. :)

With it, you can enable or disable items with item index.

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;
        }
    }
}

To use :

  • Add a custom control to your tool box and drag on your form
  • Use this methods on list box listBox1.DisableItem(index); listBox1.EnableItem(index);
  • Download this with below links

Download Source



回答2:

If for whatever reason a custom control is not appropriate you can achieve the same result from a 'visual' point of view by splitting your results into two list boxes.

1st Control: ListBoxA (Active).
2nd Control: ListBoxB (Inactive).

Add any items which are active / can be selected to ListBoxA and any items which need to be disabled to ListBoxB.

For the next part bear in mind that the default item height for a standard ListBox entry is something like 18px.

Depending on the controls draw mode / if you have overridden this

You can have the two controls aligned vertically - dynamically setting the height of the first control to 18px multiplied by the number of Items in ListBoxA

See example below: (https://snag.gy/4GHYiz.jpg)

Of course! This only helps if you don't need the disabled items to display in the given order.



回答3:

There is no native Disable/Enable items in ListBox. However you can do some tricks.

First you need to define you own class for item which will have Enabled property.

Then you need to subscribe to MouseDown event and check which (righ or left) button was clicked. And based on x,y position get the item that was clicked. Then you will set the Enabled property to True/False. Below are some examples :

Your custom class

    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;
        } 
    }

The MouseDown event

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;

    }
}