WinForms ListBox with readonly/disabled items

后端 未结 5 1594
傲寒
傲寒 2021-01-18 20:39

Is there a way to make some of the items in a ListBox readonly/disabled so they can\'t be selected? Or are there any similar controls to ListBox to provide this functionalit

相关标签:
5条回答
  • 2021-01-18 21:10

    ListBox doesn't have support for that. You can bolt something on, you could deselect a selected item. Here's a silly example that prevents even-numbered items from being selected:

    private void listBox1_SelectedIndexChanged(object sender, EventArgs e) {
      for (int ix = listBox1.SelectedIndices.Count - 1; ix >= 0; ix--) {
        if (listBox1.SelectedIndices[ix] % 2 != 0) 
          listBox1.SelectedIndices.Remove(listBox1.SelectedIndices[ix]);
      }
    }
    

    But the flicker is quite noticeable and it messes up keyboard navigation. You can get better results by using CheckedListBox, you can prevent the user from checking the box for an item:

    private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
      if (e.Index % 2 != 0) e.NewValue = CheckState.Unchecked;
    }
    

    But now you cannot override drawing to make it look obvious to the user that the item isn't selectable. No great solutions here, it is far simpler to just not display items in the box that shouldn't be selectable.

    0 讨论(0)
  • 2021-01-18 21:10

    @Hans solution causing that the item id selected for a short time and then selection disappearing. I don't like that - this can be confusing for the enduser.

    I prefer to hide some edit option buttons for the item that should be disabled:

            if (lbSystemUsers.Items.Count > 0 && lbSystemUsers.SelectedIndices.Count > 0)
                if (((RemoteSystemUserListEntity)lbSystemUsers.SelectedItem).Value == appLogin)
                {
                    bSystemUsersDelete.Visible = false;
                    bSystemUsersEdit.Visible = false;                    
                }
                else
                {
                    bSystemUsersDelete.Visible = true;
                    bSystemUsersEdit.Visible = true;
                }
    

    Here is the list that lists the users and disallow to edit user that is actually logged in to the edit panel.

    0 讨论(0)
  • 2021-01-18 21:18

    ListBox doesn't have a ReadOnly (or similar) property, but you can make a custom ListBox control. Here's a solution that worked pretty well for me:

    https://ajeethtechnotes.blogspot.com/2009/02/readonly-listbox.html

    public class ReadOnlyListBox : ListBox 
    { 
        private bool _readOnly = false; 
        public bool ReadOnly 
        { 
            get { return _readOnly; } 
            set { _readOnly = value; } 
        } 
    
        protected override void DefWndProc(ref Message m) 
        { 
            // If ReadOnly is set to true, then block any messages 
            // to the selection area from the mouse or keyboard. 
            // Let all other messages pass through to the 
            // Windows default implementation of DefWndProc.
            if (!_readOnly || ((m.Msg <= 0x0200 || m.Msg >= 0x020E) 
                && (m.Msg <= 0x0100 || m.Msg >= 0x0109) 
                && m.Msg != 0x2111 
                && m.Msg != 0x87)) 
            {
                base.DefWndProc(ref m); 
            } 
        } 
    } 
    
    0 讨论(0)
  • 2021-01-18 21:25

    I know this is old thread, but i'll post a workaround for other readers in future.

    listBox.Enabled = false;
    listBox.BackColor = Color.LightGray;
    

    This will change background color of list box to Light Gray. So this is not builtin "native way" to do it, but at least gives user some feedback that he is not supposed to / can't edit that field.

    0 讨论(0)
  • 2021-01-18 21:34

    To get read-only behaviour I have MyCBLLocked, a boolean associated with the MyCBL checkbox list control, and on the CheckItem event I do:

    private void MyCBL_ItemCheck(object sender, ItemCheckEventArgs e)
    {
        if (MyCBLLocked)
            e.NewValue = e.CurrentValue;
        }
    

    So instead of

    MyCBL.Enabled = false;
    

    I use

    MyCBLLocked = true;
    

    and the user can scroll through the many selections but not mess things up with changes.

    0 讨论(0)
提交回复
热议问题