c#/Winform

[c#] DropDown Checkedlistbox / Combobox 안에 Checkedlistbox

byH 2021. 12. 9. 21:19
728x90
반응형

콤보박스는 그룹박스나 판넬등 영역을 벗어나서 크기가 늘어날 수 있다.

그러나 체크박스는 그룹박스 크기를 벗어날 수 없었다.

그리고 콤보박스의 드롭다운이 되는 걸 체크박스리스트에 적용하고 싶어서 찾아보다가 해당 사이트를 발견했다.

그리고 시도해본 결과를 다시 정리하려고 한다 

https://www.codeproject.com/Articles/18929/An-OwnerDraw-ComboBox-with-CheckBoxes-in-the-Drop

 

An OwnerDraw ComboBox with CheckBoxes in the Drop-Down

An OwnerDraw ComboBox with CheckBoxes in the Drop-Down

www.codeproject.com

 

1. Combobox 생성 

2. Combobox의 DrawMode를 OwnerDrawFixed로 변경 

3. CLASS 추가 

public class CheckComboBoxItem
{
    public CheckComboBoxItem( string text, bool initialCheckState )
    {
        _checkState = initialCheckState;
        _text = text;
    }

    private bool _checkState = false;
    public bool CheckState
    {
        get { return _checkState; }
        set { _checkState = value; }
    }

    private string _text = "";
    public string Text
    {
        get { return _text; }
        set { _text = value; }
    }

    public override string ToString()
    {
        return "Select Options";
    }
}

 

4.DrawItem 이벤트 핸들러 추가 

콤보박스를 클릭하고 속성 창에서 노란색 번개모양을 클릭하면 사용할 수 있는 이벤트 목록들이 뜬다.

여기서 DrawItem을 더블클릭하면 자동으로 함수가 생성된다 

5. DrawItem 이벤트 함수 작성 

if (e.Index == -1)
    {
        return;
    }

    if( !( Items[ e.Index ] is CheckComboBoxItem ) )
    {
        e.Graphics.DrawString( 
            Items[ e.Index ].ToString(), 
            this.Font, 
            Brushes.Black, 
            new Point( e.Bounds.X, e.Bounds.Y ) );
        return;
    }

    CheckComboBoxItem box = (CheckComboBoxItem)Items[ e.Index ];

    CheckBoxRenderer.RenderMatchingApplicationState = true;
    CheckBoxRenderer.DrawCheckBox( 
        e.Graphics, 
        new Point( e.Bounds.X, e.Bounds.Y ), 
        e.Bounds, 
        box.Text, 
        this.Font, 
        ( e.State & DrawItemState.Focus ) == 0, 
        box.CheckState ? CheckBoxState.CheckedNormal : 
            CheckBoxState.UncheckedNormal );

소스코드를 이대로 복사해서 붙여넣으면 Items와 CheckBoxState 에서 오류가 발생한다 

 

items는 combobox의 items이다. 그래서 Item대신 Combobx1.Items를 

CheckBoxState 대신 System.Windows.Forms.VisualStyles.CheckBoxState 을 입력하면 오류가 사라진다. 

 private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index == -1)
            {
                return;
            }
            
            if (!(comboBox1.Items[e.Index] is CheckComboBoxItem))
            {
                e.Graphics.DrawString(
                    comboBox1.Items[e.Index].ToString(),
                    this.Font,
                    Brushes.Black,
                    new Point(e.Bounds.X, e.Bounds.Y));
                return;
            }

            CheckComboBoxItem box = (CheckComboBoxItem)comboBox1.Items[e.Index];

            CheckBoxRenderer.RenderMatchingApplicationState = true;
            CheckBoxRenderer.DrawCheckBox(
                e.Graphics,
                new Point(e.Bounds.X, e.Bounds.Y),
                e.Bounds,
                box.Text,
                this.Font,
                (e.State & DrawItemState.Focus) == 0,
                box.CheckState ?  System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal :
                    System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
        }

 

6. combobox에 item 추가

[form이 load할 때 추가하도록 작성해보았다.]

"one"은 text를 true는 체크상태로 할거면 true, check되지 않은상태로 할거면 false를 입력하면 된다. 

private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.Items.Add(new CheckComboBoxItem("One", true));

        }

 

7.SelectedIndexChanged 이벤트함수 추가

6번까지만 진행하면 콤보박스 안에 들어간 ITEM을 선택해도 체크에 대한 변화가 없다. 

DrawItem 이벤트 함수를 추가했을 때 처럼 콤보박스를 선택하고 속성창에서 번개모양을 눌러 SelectedIndexChanged 를 더블클릭함 

 private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            CheckComboBoxItem item = (CheckComboBoxItem)comboBox1.SelectedItem;
            item.CheckState = !item.CheckState;
        }

[추가, 여기서부터 문제여서 사용하지 않게된 이유 & 누군가 알려줬으면 하는 내용]

이렇게 하면 내가 원하는 것이 나올줄 알았는데 일단 콤보박스 너비보다 글자가 더 많을 경우 체크박스랑 글자가 합쳐진다.. 

 

가운데정렬이라 그럴까 싶어 왼쪽정렬로 변경했지만 똑같당 ㅎ 

 private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index == -1)
            {
                return;
            }
            
            if (!(comboBox1.Items[e.Index] is CheckComboBoxItem))
            {
                e.Graphics.DrawString(
                    comboBox1.Items[e.Index].ToString(),
                    this.Font,
                    Brushes.Black,
                    new Point(e.Bounds.X, e.Bounds.Y));
                return;
            }

            CheckComboBoxItem box = (CheckComboBoxItem)comboBox1.Items[e.Index];

            CheckBoxRenderer.RenderMatchingApplicationState = true;
            CheckBoxRenderer.DrawCheckBox(
                e.Graphics,
                new Point(e.Bounds.X, e.Bounds.Y),
                e.Bounds,
                box.Text,
                this.Font,
                TextFormatFlags.Left,
                (e.State & DrawItemState.Focus) == 0,
                box.CheckState ?  System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal :
                    System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
        }

진짜 이렇게라도 사용해야 할 경우라면 추천하진 않지만 "   동해물과 백두산이" 를 넣는등의 방법은 있을 것 같다 

 

또 다른 문제점은 원래 콤보박스를 클릭하면 높이가 변하면서 길게 늘어난다, 그리고 아이템을 선택하면 

원래 크기로 돌아가는데 

체크리스트박스는 여러개의 아이템을 선택하는 경우가 많은데, 한 개 선택하고 줄어들고 다시 선택하고 줄어들고 

더 귀찮은 일이 되었다 . . !

그래서 결국 안 쓰게 되었지만, 더 좋은 아이디어를 갖고 이 글이 수정되길 바란다! 

 

 

 

728x90
반응형