簡體   English   中英

如何在列表框中禁用所選項目

[英]How To Disable Selected Item In List Box

我在WinForms應用程序中有一個ListBox ,我想禁用該列表中的一些項目,例如,如果我右鍵單擊某個項目,它將被禁用,如果我左鍵單擊禁用的項目,則應啟用它。 我怎樣才能做到這一點? 非常感謝

我找到了一個方法。 我們必須創建一個自定義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);上使用此方法listBox1.DisableItem(index); listBox1.EnableItem(index); listBox1.DisableItem(index); listBox1.EnableItem(index);
  • 通過以下鏈接下載

下載源代碼

\\預習

如果由於某種原因自定義控件不合適,您可以通過將結果拆分為兩個列表框從“可視”視角獲得相同的結果。

第一個控制:ListBoxA(活動)。
第二個控件:ListBoxB(非活動)。

將任何活動/可以選擇的項目添加到ListBoxA以及需要禁用的任何項目到ListBoxB。

對於下一部分,請記住標准ListBox條目的默認項高度類似於18px。

取決於控件繪制模式/如果您已覆蓋此項

您可以將兩個控件垂直對齊 - 將第一個控件的高度動態設置為18px乘以ListBoxA中的項數

見下面的例子:( https://snag.gy/4GHYiz.jpg

https://snag.gy/4GHYiz.jpg

當然! 這僅在您不需要按給定順序顯示禁用項目時才有用。

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

MouseDown事件

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;

    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM