본문 바로가기
C# /WindowsForm

[C#] ListView Control 동적으로 Control 추가 후 Scroll 시에 위치 조정 방안

by Hwoarang757 2022. 11. 23.

[C#] ListView Control 동적으로 Control 추가 후 Scroll 시에 위치 조정 방안

 

출처 : Handling scroll event on listview in c# - Stack Overflow

 

Handling scroll event on listview in c#

I have a listview that generates thumbnail using a backgroundworker. When the listview is being scrolled i want to pause the backgroundworker and get the current value of the scrolled area, when th...

stackoverflow.com

 

 

ListView에 TextBox를 동적으로 여러 Item 을 추가 후 Scroll 시에 , 해당 Control의 Bounds의 정보는 변경되지 않아 스크롤만 움직이고 실제 TextBox는 위아래로 Position 이 변경되지 않았습니다.  

 

출처와 같이 ListViewControl에 Scroll 이벤트를 추가 하여 , Scroll 이벤트 발생 시에 , 동적으로 추가한 TextBox도 Bounds 정보를 갱신 하게끔 테스트 해보았습니다.

 

1. Class Library 프로젝트 생성 , ListView를 상속받아 , Scroll 이벤트를 추가 하였습니다.

using System.Windows.Forms;

namespace CustomListView
{
    public class CustomListView : ListView
    {
        public event ScrollEventHandler Scroll;
        protected virtual void OnScroll(ScrollEventArgs e)
        {
            ScrollEventHandler handler = this.Scroll;
            if (handler != null) handler(this, e);
        }


        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

            if (m.Msg == 0x115 || m.Msg == 0x20a) // 0x20a 는 mousewheel 움직임
            {
                OnScroll(new ScrollEventArgs((ScrollEventType)(m.WParam.ToInt32() & 0xffff), 0));
            }
        }
    }
}

 

 

2. Windows Form Application 프로젝트에 도구 상자 항목에 위에서 생성한 DLL 의 파일을 선택하여 CustomListView Control을 추가 하였습니다.

3. 테스트 코드를 작성하였습니다.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ListViewTest
{
    public partial class FrmLstTest : Form
    {
        public FrmLstTest()
        {
            InitializeComponent();
        }


        List<ListViewTextBox> lstRecvCtlList = new List<ListViewTextBox>();

        private void FrmLstTest_Load(object sender, EventArgs e)
        {
            InitControl();
        }

        private void InitControl()
        {
            lstRecv.View = View.Details;
            lstRecv.Columns.Add("TextBox1", "TextBox1", 100 , HorizontalAlignment.Center  ,0);
            lstRecv.Columns.Add("TextBox2", "TextBox2", 100, HorizontalAlignment.Center, 0 );
            lstRecv.Scroll += LstRecv_Scroll;
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            ListViewItem lvi = new ListViewItem();
            lvi.SubItems.Add(string.Empty);
            lvi.SubItems.Add(string.Empty);

            lstRecv.Items.Add(lvi);

            Rectangle rect;

            TextBox txtBox1 = new TextBox();
            txtBox1.Parent = lstRecv;
            txtBox1.TabIndex = 0;
            txtBox1.BorderStyle = BorderStyle.Fixed3D;
            

            rect = lstRecv.Items[lstRecv.Items.Count - 1].SubItems[0].Bounds;
            txtBox1.SetBounds(rect.X + 3, rect.Y, rect.Width - 6, rect.Height);
            txtBox1.Width = 100;
            txtBox1.Text = $"txtBox1={lstRecv.Items.Count}";
            
            TextBox txtBox2 = new TextBox();
            txtBox2.Parent = lstRecv;
            txtBox2.TabIndex = 1;
            txtBox2.BorderStyle = BorderStyle.Fixed3D;


            rect = lstRecv.Items[lstRecv.Items.Count - 1].SubItems[1].Bounds;
            txtBox2.SetBounds(rect.X + 3, rect.Y, rect.Width - 6, rect.Height);
            txtBox2.Text = $"txtBox2={lstRecv.Items.Count}";

            lstRecvCtlList.Add(new ListViewTextBox { textBox1 = txtBox1, textBox2 = txtBox2 });

            Debug.WriteLine(lstRecvCtlList.Count);
        }


        private void LstRecv_Scroll(object sender, ScrollEventArgs e)
        {
            if (lstRecvCtlList.Count > 0) // 해당 List는 NULL 이 아님 , Instance 생성시에 할당 됨
            {
                int idxx = 0;
                Rectangle rtTemp;
                lstRecvCtlList.ForEach(a =>
                {
                    try
                    {
                        rtTemp = lstRecv.Items[idxx].SubItems[0].Bounds;
                        a.textBox1.SetBounds(rtTemp.X + 3, rtTemp.Y, rtTemp.Width - 6, rtTemp.Height);
                        a.textBox1.Width = 100;

                        rtTemp = lstRecv.Items[idxx].SubItems[1].Bounds;
                        a.textBox2.SetBounds(rtTemp.X + 3, rtTemp.Y, rtTemp.Width - 6, rtTemp.Height);
                    }
                    catch { }

                    idxx++;
                });
            }
        }

    }



    public class ListViewTextBox
    {
        public TextBox textBox1 { get; set; }
        public TextBox textBox2 { get; set; }

    }

}