IT박스

Winforms에서 Combobox를 읽기 전용으로 만드는 방법

itboxs 2021. 1. 9. 09:38
반응형

Winforms에서 Combobox를 읽기 전용으로 만드는 방법


사용자가 콤보 상자에 표시된 값을 변경할 수 없도록하고 싶습니다. 나는 사용 Enabled = false했지만 텍스트가 회색으로 표시되어 읽기가 어렵습니다. ReadOnly = true텍스트가 정상적으로 표시되는 텍스트 상자처럼 작동하고 싶지만 사용자가 편집 할 수 없습니다.

이것을 달성하는 방법이 있습니까?


ComboBox-with-read-only-behavior 기사 는 흥미로운 솔루션을 제안합니다.

동일한 위치에 읽기 전용 텍스트 상자와 콤보 상자를 모두 만듭니다. 읽기 전용 모드를 원하면 텍스트 상자를 표시하고 편집 가능하게하려면 콤보 상자를 표시합니다.


대신에 DropDownStyle속성을 만들어 이벤트를 처리하여 사용자가 텍스트를 변경하지 못하도록합니다.DropDownListDropDownTextChanged


이것이 당신이 찾고있는 것인지 확실하지 않지만 ...

DropDownStyle = DropDownList 설정

그런 다음 SelectedIndexChanged 이벤트에서

If (ComboBox1.SelectedIndex <> 0)
{
    ComboBox1.SelectedIndex = 0
}

이 추악한 부분은 그들이 그것을 바꿀 수있는 것처럼 "느껴질 것"입니다. 값을 변경할 수없는 이유를 알려주지 않는 한 오류라고 생각할 수 있습니다.


제가 제안 할 수있는 가장 좋은 방법은 콤보 상자를 읽기 전용 텍스트 상자 (또는 레이블)로 바꾸는 것입니다. 이렇게하면 사용자가 값을 계속 선택 / 복사 할 수 있습니다.

물론, 다른 건방진 전술을 설정하는 것 DropDownStyleDropDownList, 단지 다른 모든 옵션을 제거 - 다음 사용자는 ;-p 선택하는 아무 것도 없습니다


여기에 링크 설명 입력

그냥 변경 DropDownStyleDropDownList. 또는 완전히 읽기 전용으로 설정하려면을 설정할 수 있습니다 Enabled = false. 또는 그 모양이 마음에 들지 않으면 때때로 두 개의 컨트롤, 읽기 전용 텍스트 상자와 콤보 상자 하나가 있고 콤보를 숨기고 완전히 읽기 전용이어야하는 경우 텍스트 상자를 표시합니다. 그 반대.


ComboBox를 서브 클래 싱하여 설정시 자신을 숨기고 동일한 텍스트를 포함하는 ReadOnly TextBox를 맨 위에 표시하는 ReadOnly 속성을 추가하여 처리했습니다.

class ComboBoxReadOnly : ComboBox
{
    public ComboBoxReadOnly()
    {
        textBox = new TextBox();
        textBox.ReadOnly = true;
        textBox.Visible = false;
    }

    private TextBox textBox;

    private bool readOnly = false;

    public bool ReadOnly
    {
        get { return readOnly; }
        set
        {
            readOnly = value;

            if (readOnly)
            {
                this.Visible = false;
                textBox.Text = this.Text;
                textBox.Location = this.Location;
                textBox.Size = this.Size;
                textBox.Visible = true;

                if (textBox.Parent == null)
                    this.Parent.Controls.Add(textBox);
            }
            else
            {
                this.Visible = true;
                this.textBox.Visible = false;
            }
        }
    }
}

다음은 ReadOnly Combo를위한 최상의 솔루션입니다.

private void combo1_KeyPress(object sender, KeyPressEventArgs e)
{
    e.KeyChar = (char)Keys.None;
}

Combo에 대한 키 누르기를 버립니다.


마이클 R의 코드 작품,하지만 ...
DropDownHeight = 1;읽기 전용 속성이 false로 설정되어있을 때 기본 값으로 다시해야합니다. 따라서 앞에 삽입하십시오 base.OnDropDown(e).DropDownHeight = 106;

using System;
using System.Threading;
using System.Windows.Forms;

namespace Test_Application
{
    class ReadOnlyComboBox : ComboBox
    {
        private bool _readOnly;
        private bool isLoading;
        private bool indexChangedFlag;
        private int lastIndex = -1;
        private string lastText = "";

        public ReadOnlyComboBox()
        {
        }

        public bool ReadOnly
        {
            get { return _readOnly; }
            set { _readOnly = value; }
        }

        protected override void OnDropDown (EventArgs e)
        {
            if (_readOnly)
            {
                DropDownHeight = 1;
                var t = new Thread(CloseDropDown);
                t.Start();
                return;
            }
            DropDownHeight = 106; //Insert this line.
            base.OnDropDown(e);
        }

        private delegate void CloseDropDownDelegate();
        private void WaitForDropDown()
        {
            if (InvokeRequired)
            {
                var d = new CloseDropDownDelegate (WaitForDropDown);
                Invoke(d);
            }
            else
            {
                DroppedDown = false;
            }
        }
        private void CloseDropDown()
        {
            WaitForDropDown();
        }

        protected override void OnMouseWheel (MouseEventArgs e)
        {
            if (!_readOnly) 
                base.OnMouseWheel(e);
        }

        protected override void OnKeyDown (KeyEventArgs e)
        {
            if (_readOnly)
            {
                switch (e.KeyCode)
                {
                    case Keys.Back:
                    case Keys.Delete:
                    case Keys.Up:
                    case Keys.Down:
                        e.SuppressKeyPress = true;
                        return;
                }
            }
            base.OnKeyDown(e);
        }

        protected override void OnKeyPress (KeyPressEventArgs e)
        {
            if (_readOnly)
            {
                e.Handled = true;
                return;
            }
            base.OnKeyPress(e);
        }
    }
}

이 답변을 완료하려면 :

파일-> 새로 만들기-> 프로젝트 ... Visual C #-> Windows-> 클래식 데스크톱-> Windows Forms 컨트롤 라이브러리

컨트롤의 이름-확인을 입력하고이 코드를 붙여 넣습니다.

dll 파일의 이름을 선택할 수 있습니다.
Project-yourproject Properties ...

  • 어셈블리 이름 : 이름을 입력하십시오. 솔루션을 빌드하면 dll 파일이 있습니다. 따라서 읽기 전용 콤보를 사용하려는 프로젝트를 열고 참조를 마우스 오른쪽 버튼으로 클릭합니다.
  • 참조를 추가하고 dll 파일을 찾습니다. 사용자 컴포넌트를 Toolbox에 삽입하려면 Toolbox를 열고 일반 탭-> 항목 선택 ...을 마우스 오른쪽 버튼으로 클릭합니다.
  • dll 파일 찾아보기-열기. 이제 프로젝트에서 ReadOnlyComboBox를 사용할 수 있습니다. 추신 : 저는 VS2015를 사용하고 있습니다.

활성화 된 콤보 상자의 경우 앞색과 배경색을 시스템 색상으로 변경할 수 있지만, 사용자가 혼동을 줄 수 있지만 (변경할 수없는 경우 사용하는 이유) 더 좋아 보일 것입니다.


다음은 ComboBoxwith Enabled = False가 읽기 어렵다는 사실을 해결하는 방법입니다 .

비활성화되었을 때 괜찮아 보이는 콤보 박스


왜 그냥 텍스트 상자를 사용하지 않습니까? 텍스트 상자에는 "읽기 전용"속성이 있으며 콤보 상자에 데이터 만 표시하기를 원하기 때문에 콤보 상자가 필요한 이유를 알 수 없습니다.

대안은 "값이 변경됨"이벤트에 대한 입력을 취소하는 것입니다. 그러면 사용자가 무엇을하든 상관없이 정보를 표시 할 수 있습니다.


사실, 다소 간단합니다.

Private Sub combobox1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles combobox1.KeyDown
    ' the following makes this the combobox read only    
    e.SuppressKeyPress = True    
End Sub

DropdownStyle속성 설정Simple

KeyPressComboBox 이벤트에 아래 코드 추가

private void comboBoxName_KeyPress(object sender, KeyPressEventArgs e)
{
    e.Handled = true;
    return;
}

KeyDownComboBox 이벤트에 아래 코드 추가

private void comboBoxName_KeyDown(object sender, KeyEventArgs e)
{
    e.Handled = true;
    return;
}

If you've already populated it, and selected the appropriate item, and made it a DropDownList, then you can use an extension method like this to quickly reduce the selection list down to just the selected item:

public static void MakeReadOnly(this ComboBox pComboBox) {
   if (pComboBox.SelectedItem == null)
      return;

   pComboBox.DataSource = new List<object> {
      pComboBox.SelectedItem
   };
}

I know that I'm a little late to the party, but I was researching this exact question and I knew that there had to be some way to make the combobox readonly as if it were a textbox and disabled the list popping up. It's not perfect, but it is definitely better than all of the answers I've been finding all over the internet that don't work for me. After the button is pressed and the OnDropDown is called, a new thread is created that will set the DroppedDown property to false, thus creating the effect of "nothing happening." The mouse wheel is consumed and key events are consumed as well.

using System;
using System.Threading;
using System.Windows.Forms;

namespace Test_Application
{
    class ReadOnlyComboBox : ComboBox
    {
        private bool _readOnly;
        private bool isLoading;
        private bool indexChangedFlag;
        private int lastIndex = -1;
        private string lastText = "";

        public ReadOnlyComboBox()
        {
        }

        public bool ReadOnly
        {
            get { return _readOnly; }
            set { _readOnly = value; }
        }

        protected override void OnDropDown(EventArgs e)
        {
            if (_readOnly)
            {
                DropDownHeight = 1;
                var t = new Thread(CloseDropDown);
                t.Start();
                return;
            }
            base.OnDropDown(e);
        }

        private delegate void CloseDropDownDelegate();
        private void WaitForDropDown()
        {
            if (InvokeRequired)
            {
                var d = new CloseDropDownDelegate(WaitForDropDown);
                Invoke(d);
            }
            else
            {
                DroppedDown = false;
            }
        }
        private void CloseDropDown()
        {
            WaitForDropDown();
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            if (!_readOnly) 
                base.OnMouseWheel(e);
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (_readOnly)
            {
                switch (e.KeyCode)
                {
                    case Keys.Back:
                    case Keys.Delete:
                    case Keys.Up:
                    case Keys.Down:
                        e.SuppressKeyPress = true;
                        return;
                }
            }
            base.OnKeyDown(e);
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            if (_readOnly)
            {
                e.Handled = true;
                return;
            }
            base.OnKeyPress(e);
        }
    }
}

Simplest way in code:

instead of adding methods for KeyPress or KeyDown, add this code on 'Form1_Load' method:

comboBox1.KeyPress += (sndr, eva) => eva.Handled = true;

or

comboBox1.KeyDown += (sndr, eva) => eva.SuppressKeyPress = true;

(sndr, eva) is for (object sender, EventArgs e)


Here is the Best solution for the ReadOnly Combo.

private void combo1_KeyPress(object sender, KeyPressEventArgs e) {
    e.KeyChar = (char)Keys.None; 
} 

It will discard the keypress for the Combo. It doesn't have "e.KeyChar" !

ReferenceURL : https://stackoverflow.com/questions/392098/how-to-make-combobox-in-winforms-readonly

반응형