winform .net 최상의 방법 DatagridView에 이미지를 표시하려는 경우
-
19-09-2019 - |
문제
Net WebDeveloper 및 일반적으로 Win32 앱을 만들지 않습니다. 하지만 지금은해야합니다. 약 2000 개의 항목이있는 목록이 있습니다. 각 항목은 다른 레이블과 그림이있는 레이블로 표시해야합니다. FlowLayoutPanel로 이것을 만들었고 레이블, 텍스트 상자, 레이블 및 그림 상자를 사용하여 각 항목에 대한 패널을 만들기 위해 항목에서 foreach를 수행했습니다.
이제 1000 개의 항목을 초과 할 때 문제가 발생했습니다. 그래서 ListView 또는 DataGridView를 사용해야한다는 것을 읽었습니다.
이제 다음과 같은 DataGridView가 있습니다.
DataGridView dgv = new DataGridView();
dgv.AutoSize = true;
dgv.ScrollBars = ScrollBars.Vertical;
System.Data.DataTable dt = new System.Data.DataTable();
DataColumn dc1 = new DataColumn("Code", typeof(string));
dc1.ReadOnly = true;
dt.Columns.Add(dc1);
dt.Columns.Add(new DataColumn("Quantity", typeof(int)));
DataColumn dc3 = new DataColumn("Price", typeof(string));
dc3.ReadOnly = true;
dt.Columns.Add(dc3);
dt.Columns.Add(new DataColumn("Image", typeof(Bitmap)));
foreach (Product pd in products)
{
DataRow dr = dt.NewRow();
dr["Code"] = pd.ProductCode;
dr["Quantity"] = pd.ProductQuantity;
dr["Price"] = "€ " + String.Format("{0:0,00}", pd.ProductResalePrice.ToString());
dr["Image"] = BitmapFromWeb(pd.ProductImage);
dt.Rows.Add(dr);
}
dt.AcceptChanges();
dgv.RowTemplate.Height = 50;
dgv.DataSource = dt;
그러나 문제는 DatagridView의 비트 맵이 정말 느리다는 것입니다! 훨씬 더 빠른 곳에서 이전에 가지고 있던 PictueBox 옵션과 패널. 이것을 어떻게 해결합니까?
두 번째 질문은 다음과 같습니다. 두 번째 열에서 변경된 변경 사항을 추적 할 때 어떤 이벤트가 필요합니까?
OW 한 가지 : 이미지는 온라인으로 사용할 수 있으므로 'Pd.Productionage'는 URL입니다.
private static Bitmap BitmapFromWeb(string URL)
{
try
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(URL);
myRequest.Method = "GET";
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(myResponse.GetResponseStream());
myResponse.Close();
return bmp;
}
catch (Exception ex)
{
return null; // if for some reason we couldn't get to image, we return null
}
}
해결책
이미지를 비동기로로드 한 다음 셀의 새로 고침을 강제로합니다. Foreach 코드를 ThreadPool로 호출 할 수 있습니다.
ThreadPool.QueueUserWorkItem(delegate
{
foreach (DataRow row in dt)
{
row["Image"] = BitmapFromWeb(Products[row["Code"]].ProductImage);
//maybe a call to invalidate here, remember to do Control.Invoke(...)
}
}
편집 : 다음은 양식 생성자 내에서 테스트 한 샘플 코드입니다.
DataTable t= new DataTable();
t.Columns.Add("id");
t.Columns.Add("uri");
t.Columns.Add(new DataColumn("Img",typeof(Bitmap)));
Bitmap b = new Bitmap(50, 15);
using (Graphics g = Graphics.FromImage(b))
{
g.DrawString("Loading...", this.Font, new SolidBrush(Color.Black), 0f,0f);
}
t.Rows.Add(new object[] { "1", "http://farm1.static.flickr.com/88/377522544_c4774f15cc_s.jpg", b });
t.Rows.Add(new object[] { "2", "http://farm1.static.flickr.com/175/377522405_2c505def99_s.jpg", b });
t.Rows.Add(new object[] { "3", "http://farm1.static.flickr.com/185/377524902_72f82e2db9_s.jpg", b });
t.Rows.Add(new object[] { "4", "http://farm1.static.flickr.com/136/377524944_d011abf786_s.jpg", b });
t.Rows.Add(new object[] { "5", "http://farm1.static.flickr.com/137/377528675_d3b9d541fb_s.jpg", b });
dataGridView1.DataSource = t;
ThreadPool.QueueUserWorkItem(delegate
{
foreach (DataRow row in t.Rows)
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(row["uri"].ToString());
myRequest.Method = "GET";
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(myResponse.GetResponseStream());
myResponse.Close();
row["Img"] = bmp;
}
});
dataGridView1.CellEndEdit += dataGridView1_CellEndEdit;
.... 그리고 셀 끝 편집 코드 :
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
string value = dataGridView1.Rows[e.RowIndex].Cells["uri"].Value.ToString();
ThreadPool.QueueUserWorkItem(delegate
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(value);
myRequest.Method = "GET";
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(myResponse.GetResponseStream());
myResponse.Close();
dataGridView1.Rows[e.RowIndex].Cells["Img"].Value=bmp;
});
}
다른 팁
// table is DataTable object declared as member in my form class
table = new DataTable();
table.Columns.Add(new DataColumn("Column1", typeof(string)));
table.Columns.Add(new DataColumn("Column2", typeof(string)));
table.Columns.Add(new DataColumn("Column3", typeof(System.Drawing.Bitmap)));
dataGridView1.DataSource = table;
제휴하지 않습니다 StackOverflow